[{"data":1,"prerenderedAt":4373},["ShallowReactive",2],{"blog-google-kodak-moment-open-source-strategy":3,"blog-adjacent-google-kodak-moment-open-source-strategy":784,"blog-related-google-kodak-moment-open-source-strategy":2292},{"id":4,"title":5,"body":6,"category":766,"cover":16,"date":767,"description":768,"draft":769,"extension":770,"meta":771,"navigation":772,"path":773,"readingTime":774,"seo":775,"stem":776,"tags":777,"__hash__":783},"blogs\u002Fblogs\u002Fgoogle-kodak-moment-open-source-strategy.md","Back to the Android Playbook: How Google Can Break Free from Its Kodak Moment",{"type":7,"value":8,"toc":733},"minimark",[9,17,27,30,33,36,41,44,47,55,59,62,67,128,131,135,146,149,155,159,162,166,169,176,198,204,208,212,215,222,225,251,257,261,264,269,272,292,295,299,302,305,322,325,329,332,353,357,360,367,370,372,383,385,387,392,399,401,404,407,411,414,417,424,428,431,435,489,492,496,505,508,514,518,521,525,528,535,552,558,562,566,569,576,579,605,611,615,618,623,626,646,649,653,656,659,676,679,683,686,706,709,712,719,722,724],[10,11,12],"p",{},[13,14],"img",{"alt":15,"src":16},"cover","https:\u002F\u002Fimages.xtop.dev\u002Fblogs\u002F2026\u002F08\u002Fgoogle-kodak-moment-cover.webp",[18,19,20],"blockquote",{},[10,21,22,23],{},"📖 ",[24,25,26],"em",{},"中文版在下方 — scroll down for the Chinese version.",[28,29],"hr",{},[10,31,32],{},"Today's Google (Alphabet) stands at a crossroads. It's caught between the anxiety of its search ad empire being eroded and the trap of chasing OpenAI's playbook in the generative AI wave. This posture — inventing the future but being held hostage by the existing cash cow — looks eerily similar to Kodak, which invented the digital camera and still went bankrupt.",[10,34,35],{},"But Google's biggest mistake isn't falling behind on technology. It's blindly treating OpenAI as the only paradigm for AI.",[37,38,40],"h2",{"id":39},"kodaks-lesson-invented-the-future-died-in-the-past","Kodak's Lesson: Invented the Future, Died in the Past",[10,42,43],{},"In 1975, Kodak engineer Steve Sasson built the world's first digital camera. Management's first reaction wasn't excitement — it was fear: \"This thing will kill our film business.\"",[10,45,46],{},"Kodak's film empire was enormously profitable: high margins, a massive printing ecosystem, global distribution channels. Management instinctively shelved the digital camera to protect the cash cow, and was ultimately destroyed by the very future they had invented.",[10,48,49,50,54],{},"This is what Clayton Christensen defined as the ",[51,52,53],"strong",{},"\"Innovator's Dilemma\""," — successful companies trapped by their own success.",[37,56,58],{"id":57},"googles-kodak-symptoms","Google's \"Kodak Symptoms\"",[10,60,61],{},"Today's Google shows strikingly similar symptoms across multiple dimensions.",[63,64,66],"h3",{"id":65},"_1-the-cash-cow-shackle","1. The Cash Cow Shackle",[68,69,70,85],"table",{},[71,72,73],"thead",{},[74,75,76,79,82],"tr",{},[77,78],"th",{},[77,80,81],{},"Kodak",[77,83,84],{},"Google",[86,87,88,102,115],"tbody",{},[74,89,90,96,99],{},[91,92,93],"td",{},[51,94,95],{},"Core Revenue",[91,97,98],{},"Film sales (razor-and-blade model)",[91,100,101],{},"Search ads (70%+ of revenue)",[74,103,104,109,112],{},[91,105,106],{},[51,107,108],{},"Disruptive Threat",[91,110,111],{},"Digital photography",[91,113,114],{},"Generative AI direct answers",[74,116,117,122,125],{},[91,118,119],{},[51,120,121],{},"Dilemma",[91,123,124],{},"Promote digital cameras = kill film",[91,126,127],{},"Promote AI answers = cannibalize blue links",[10,129,130],{},"When users shift from \"scanning a list of links\" to \"getting direct answers,\" Google's most profitable sponsored link placements lose their conversion value. Same logic as digital photos shutting down print shops.",[63,132,134],{"id":133},"_2-invented-the-future-trapped-by-the-future","2. Invented the Future, Trapped by the Future",[10,136,137,138,141,142,145],{},"In 2017, Google published the landmark paper ",[24,139,140],{},"Attention Is All You Need",", introducing the ",[51,143,144],{},"Transformer"," architecture that directly ignited this round of AI revolution. Even core concepts like \"Hallucination\" were first coined by Google researchers.",[10,147,148],{},"Yet it was OpenAI that turned Transformers into a disruptive consumer product (ChatGPT).",[10,150,151,152],{},"The root cause: Google feared AI hallucinations would damage its commercial reputation and worried AI direct answers would cannibalize search results, leading to indecisive, slow product execution. ",[51,153,154],{},"Exactly like Kodak inventing the digital camera but not daring to promote it.",[63,156,158],{"id":157},"_3-big-company-disease","3. Big Company Disease",[10,160,161],{},"Kodak had layers of middle management and bureaucratic processes; Google has been equally plagued by \"big company syndrome\" in recent years — countless overlapping internal projects (remember all those messaging apps that were built and killed?), with employees incentivized toward promotion-friendly micro-innovations rather than risky disruption of existing business lines.",[37,163,165],{"id":164},"why-google-shouldnt-try-to-be-the-next-openai","Why Google Shouldn't Try to Be the Next OpenAI",[10,167,168],{},"OpenAI follows a classic \"unicorn model\" — high cost, closed source, monetized through premium subscriptions. If Google tries to compete head-on in this lane, it's fighting with its weakness against the competitor's strength, while also bearing the burden of its search ads being cannibalized.",[10,170,171,172,175],{},"Looking back at Google's rise, its core moat was never proprietary closed technology — it was ",[51,173,174],{},"ecosystem dominance through openness",":",[177,178,179,186,192],"ul",{},[180,181,182,185],"li",{},[51,183,184],{},"Android",": defeated Windows Phone and Symbian through open source, monopolizing global mobile traffic via bundled services",[180,187,188,191],{},[51,189,190],{},"Chromium",": open-sourced the browser engine, destroyed IE, and made Chrome the internet's default gateway",[180,193,194,197],{},[51,195,196],{},"Kubernetes & TensorFlow",": open-sourced cloud-native standards and deep learning frameworks, establishing Google's authority in the developer community",[10,199,200,203],{},[51,201,202],{},"Open source is the antibody in Google's bloodstream."," When you apply this logic to the AI era, the answer becomes clear.",[37,205,207],{"id":206},"the-breakout-triangle-open-source-small-models-hardware-alliance","The Breakout Triangle: Open Source × Small Models × Hardware Alliance",[63,209,211],{"id":210},"i-open-source-the-symmetric-weapon-against-closed-walls","I. Open Source: The Symmetric Weapon Against Closed Walls",[10,213,214],{},"When every developer and enterprise in the world can access industrial-grade open-source models with zero barriers, OpenAI's expensive subscription and API model rapidly loses its justification.",[10,216,217,218,221],{},"More importantly — ",[51,219,220],{},"the endgame of software is ecosystem",". As long as millions of developers worldwide build fine-tunes and applications on Google's open-source framework, Google retains control of AI's technical standards.",[10,223,224],{},"But Google isn't doing this well enough. Take the Gemma series as an example — its open-source strategy exposes several critical flaws:",[177,226,227,233,239,245],{},[180,228,229,232],{},[51,230,231],{},"\"Wants to open source, but won't give the good stuff\"",": core technology and large-parameter models are all locked behind closed APIs; what's open-sourced is the B-team",[180,234,235,238],{},[51,236,237],{},"Safety reins pulled too tight",": excessive alignment makes the model rigid and lifeless in creative tasks and open discussions",[180,240,241,244],{},[51,242,243],{},"Code capability cliff",": same-size Gemma consistently gets outperformed by Qwen and even DeepSeek on code benchmarks",[180,246,247,250],{},[51,248,249],{},"Starved community ecosystem",": Gemma-related derivative projects on Hugging Face lag far behind the Qwen and DeepSeek ecosystems in both quantity and quality",[10,252,253,254],{},"By contrast, the teams truly practicing the spirit of open source are Chinese organizations. DeepSeek built open-source models rivaling GPT-4 at a fraction of the training cost, winning global developer respect through sheer technical transparency. Alibaba Cloud's Qwen series covers dialogue, code, and multimodal tasks, with Hugging Face community activity and derivative ecosystems already far surpassing Gemma. ",[51,255,256],{},"A search giant invented the Transformer, yet the fruits of the open-source ecosystem were picked by startups and latecomers — this is the reality that should alarm Google most.",[63,258,260],{"id":259},"ii-small-language-models-slm-the-volume-play-for-device-dominance","II. Small Language Models (SLM): The Volume Play for Device Dominance",[10,262,263],{},"OpenAI's paradigm led the industry toward a blind worship of \"bigger is better\" — trillion-parameter models are certainly smart, but their high latency, high cost, and extreme power consumption make mass adoption impossible.",[10,265,266],{},[51,267,268],{},"AI's endgame isn't cloud-based compute dominance — it's ubiquitous on-device intelligence.",[10,270,271],{},"What can actually reach billions of users daily are 3B to 8B parameter models that run directly on devices. This is precisely the battlefield where Google holds an overwhelming advantage:",[177,273,274,280,286],{},[180,275,276,279],{},[51,277,278],{},"Controls the ultimate entry points",": Android and Chrome reach billions of users globally",[180,281,282,285],{},[51,283,284],{},"Local, instant response",": embed competitive small open-source models natively into the OS — users need no internet, no API payments",[180,287,288,291],{},[51,289,290],{},"Privacy and security",": data never leaves the device, naturally complying with privacy regulations",[10,293,294],{},"Win the devices with small models, and you win the broadest consumer market.",[63,296,298],{"id":297},"iii-ally-with-intel-and-amd-build-the-anti-nvidia-compute-alliance","III. Ally with Intel and AMD: Build the Anti-Nvidia Compute Alliance",[10,300,301],{},"In the cloud, Nvidia has built an extraordinarily stubborn compute monopoly with GPUs and CUDA; the OpenAI model turns the entire industry into Nvidia's \"tenants.\" Google fighting alone with TPU in the cloud is still playing by the opponent's rules.",[10,303,304],{},"The key to breaking through is shifting the perspective from cloud to edge, forming a deep hardware-software alliance with Intel and AMD:",[177,306,307,312,317],{},[180,308,309],{},[51,310,311],{},"Intel and AMD control the world's dominant CPU and next-gen NPU ecosystem",[180,313,314],{},[51,315,316],{},"Google deeply optimizes small open-source models for Intel NPU and AMD Ryzen AI\u002FROCm architectures",[180,318,319],{},[51,320,321],{},"Achieving zero-barrier local inference, bypassing expensive GPU requirements",[10,323,324],{},"When \"Google open-source model + Intel\u002FAMD chip\" becomes the factory default for AI PCs, billions of edge devices worldwide become the breeding ground for Google's ecosystem.",[37,326,328],{"id":327},"why-google-hesitates","Why Google Hesitates",[10,330,331],{},"If open-source ecosystem is in Google's DNA, why is it moving so cautiously? Three reasons:",[333,334,335,341,347],"ol",{},[180,336,337,340],{},[51,338,339],{},"Financial sunk cost",": training top-tier hundred-billion-parameter models costs hundreds of millions of dollars. Under Wall Street's quarterly earnings pressure, management struggles to commit to giving away top models for free",[180,342,343,346],{},[51,344,345],{},"Safety liability",": as a megacorp, if Google open-sources a top model that gets misused, the regulatory accountability and PR risk far exceed what a startup would face",[180,348,349,352],{},[51,350,351],{},"Internal strategic tug-of-war",": Google still hasn't truly chosen between \"use closed models to defend the search ad base\" and \"go full open source to rebuild the cloud ecosystem\"",[37,354,356],{"id":355},"conclusion","Conclusion",[10,358,359],{},"OpenAI is an episode in AI's early evolution, not the industry's final paradigm.",[10,361,362,363,366],{},"From \"blindly chasing closed-source APIs\" to ",[51,364,365],{},"\"open-source top models + small models to capture devices + hardware alliances to empower the ecosystem + GCP to harvest the compute infrastructure\""," — this isn't just a return to Google's historical DNA; it's the only path away from its Kodak Moment.",[10,368,369],{},"Drop the ego, break the old paradigm, re-embrace developers and hardware allies — and the Google that once rewrote the rules can do it again, on its own terms.",[28,371],{},[10,373,374],{},[24,375,376,377,382],{},"This article is a personal observation on Google's strategic dilemma. If you're interested in full-stack development or AI application deployment, feel free to ",[378,379,381],"a",{"href":380},"\u002Fservices#contact","get in touch",".",[28,384],{},[28,386],{},[388,389,391],"h1",{"id":390},"重回-android-时代google-摆脱柯达魔咒的破局之道","重回 Android 时代：Google 摆脱「柯达魔咒」的破局之道",[18,393,394],{},[10,395,22,396],{},[24,397,398],{},"English version above — scroll up for the English translation.",[28,400],{},[10,402,403],{},"今天的 Google（Alphabet）正伫立在命运的十字路口。它深陷于\"传统搜索广告被侵蚀\"的焦虑，又在生成式 AI 的浪潮中陷入了追赶 OpenAI 的误区。这种\"发明了未来却被现有现金牛困住\"的姿态，像极了当年发明数码相机却最终倒下的柯达。",[10,405,406],{},"但 Google 最大的失误，并不是技术落后，而是盲目地将 OpenAI 视为 AI 的唯一范式。",[37,408,410],{"id":409},"柯达的教训发明了未来却死在了过去","柯达的教训：发明了未来，却死在了过去",[10,412,413],{},"1975 年，柯达工程师 Steve Sasson 发明了世界上第一台数码相机。管理层看到这项技术后的第一反应不是兴奋，而是恐惧——\"这玩意会杀死我们的胶卷业务\"。",[10,415,416],{},"柯达的胶卷帝国太赚钱了：高毛利、庞大的冲印生态系统、全球化的渠道网络。管理层出于保护核心现金牛的本能，将数码相机束之高阁，最终被自己发明的未来彻底颠覆。",[10,418,419,420,423],{},"这就是克莱顿·克里斯坦森所定义的 ",[51,421,422],{},"\"创新者的窘境\"（Innovator's Dilemma）","——成功企业被自身的成功所困。",[37,425,427],{"id":426},"google-的柯达式隐患","Google 的\"柯达式隐患\"",[10,429,430],{},"对比今天的 Google，它在多个维度上表现出了极其相似的症状。",[63,432,434],{"id":433},"_1-现金牛的枷锁","1. 现金牛的枷锁",[68,436,437,448],{},[71,438,439],{},[74,440,441,443,446],{},[77,442],{},[77,444,445],{},"柯达",[77,447,84],{},[86,449,450,463,476],{},[74,451,452,457,460],{},[91,453,454],{},[51,455,456],{},"核心营收",[91,458,459],{},"胶卷销售（剃刀模式）",[91,461,462],{},"搜索广告（超过 70% 营收）",[74,464,465,470,473],{},[91,466,467],{},[51,468,469],{},"颠覆性威胁",[91,471,472],{},"数码摄影",[91,474,475],{},"生成式 AI 直答",[74,477,478,483,486],{},[91,479,480],{},[51,481,482],{},"两难困境",[91,484,485],{},"推广数码相机 = 自杀胶卷业务",[91,487,488],{},"推广 AI 直答 = 蚕食蓝色链接广告位",[10,490,491],{},"当用户获取信息的方式从\"在链接列表中筛选\"变成\"直接获取答案\"，Google 最赚钱的赞助商链接广告位就失去了转化价值。这和当年数码照片让冲印店关门是同一个逻辑。",[63,493,495],{"id":494},"_2-发明了未来却被未来困住","2. 发明了未来，却被未来困住",[10,497,498,499,501,502,504],{},"2017 年，Google 发表了划时代的论文 ",[24,500,140],{},"，提出了 ",[51,503,144],{}," 架构，直接开创了这一轮 AI 革命的技术基础。甚至\"Hallucination（幻觉）\"等核心概念也是 Google 研究员率先提出的。",[10,506,507],{},"然而，将 Transformer 转化为颠覆性消费级产品（ChatGPT）的却是 OpenAI。",[10,509,510,511],{},"根源在于：Google 既担心 AI 幻觉破坏商业声誉，又担心 AI 直答取代搜索结果，最终在产品化上举棋不定、步子太慢。",[51,512,513],{},"和柯达发明数码相机却不敢推广，如出一辙。",[63,515,517],{"id":516},"_3-大企业病","3. 大企业病",[10,519,520],{},"柯达有庞大的中层管理体系和官僚流程；Google 近年来同样饱受\"大公司病\"诟病——内部项目众多但缺乏统筹（回忆一下那些被反复重做又被砍掉的通讯应用），员工倾向于做能\"升职加薪\"的微创新，而不是承担风险去颠覆现有业务。",[37,522,524],{"id":523},"为什么-google-不应该成为第二个-openai","为什么 Google 不应该成为第二个 OpenAI",[10,526,527],{},"OpenAI 走的是典型的\"独角兽模式\"——高造价、高闭源、靠卖高价订阅变现。如果 Google 跟着在这条赛道上死磕，不仅要背负搜索广告被侵蚀的包袱，更是用自己的短板去拼别人的长板。",[10,529,530,531,534],{},"回顾 Google 的崛起史，它的核心壁垒从不是封闭的独占技术，而是 ",[51,532,533],{},"开放生态的统治力","：",[177,536,537,542,547],{},[180,538,539,541],{},[51,540,184],{},"：通过开源击败了 Windows Phone 和 Symbian，靠内置服务垄断了全球移动端流量",[180,543,544,546],{},[51,545,190],{},"：将浏览器底层开源，彻底瓦解了 IE，让 Chrome 成为互联网的绝对入口",[180,548,549,551],{},[51,550,196],{},"：将云原生标准和深度学习框架开源，奠定了 Google 在技术社区的宗师地位",[10,553,554,557],{},[51,555,556],{},"开源才是 Google 血液里自带的抗体。"," 当你把这个逻辑套用到 AI 时代，答案就清晰了。",[37,559,561],{"id":560},"破局三角开源-精简模型-硬件联盟","破局三角：开源 × 精简模型 × 硬件联盟",[63,563,565],{"id":564},"一开源瓦解闭源高墙的对称武器","一、开源：瓦解闭源高墙的对称武器",[10,567,568],{},"当全天下的开发者与企业都能无门槛获得工业级的开源模型时，OpenAI 式的高昂订阅与 API 模式将迅速失去合理性。",[10,570,571,572,575],{},"更重要的是——",[51,573,574],{},"软件的终局是生态","。只要全球上百万开发者基于 Google 的开源框架做微调和应用开发，未来的 AI 技术标准就依然掌握在 Google 手中。",[10,577,578],{},"但 Google 目前做得还不够好。以 Gemma 系列为例，它的开源策略暴露了几个致命问题：",[177,580,581,587,593,599],{},[180,582,583,586],{},[51,584,585],{},"\"既想开源，又舍不得给好料\"","：核心的优秀技术和超大参数量全都锁在闭源 API 后面，开源的只是\"次等马\"",[180,588,589,592],{},[51,590,591],{},"安全缰绳套得太紧","：过度对齐（Alignment）导致模型在创意任务和开放性讨论中生硬死板",[180,594,595,598],{},[51,596,597],{},"代码能力断崖式落后","：同尺寸的 Gemma 在代码基准测试中往往被 Qwen 甚至 DeepSeek 完虐",[180,600,601,604],{},[51,602,603],{},"社区生态匮乏","：Hugging Face 上围绕 Gemma 的二次开发项目数量和质量远落后于 Qwen 和 DeepSeek 生态",[10,606,607,608],{},"相比之下，真正在践行开源精神的是中国团队。DeepSeek 以极低的训练成本打造出性能比肩 GPT-4 的开源模型，直接用技术透明度赢得了全球开发者的尊重；阿里云的 Qwen 系列则从对话、代码到多模态全面开花，在 Hugging Face 上的社区活跃度和二次开发生态已经远超 Gemma。",[51,609,610],{},"一个搜索巨头发明了 Transformer，开源生态的果实却被创业公司和后来者摘走——这才是 Google 最应该警醒的现实。",[63,612,614],{"id":613},"二精简模型slm占据终端的走量杀手锏","二、精简模型（SLM）：占据终端的走量杀手锏",[10,616,617],{},"OpenAI 的范式将行业引向了\"越大越好\"的盲目崇拜——千亿参数的模型固然聪明，但高延迟、高成本、极度烧电，根本无法支撑大规模普及应用。",[10,619,620],{},[51,621,622],{},"AI 的终局绝非云端的算力霸权，而是无处不在的端侧智能。",[10,624,625],{},"真正能走进亿万用户日常的，是 3B 到 8B 参数量级、能够直接跑在设备上的精简模型。这恰恰是 Google 拥有压倒性优势的绝对主场：",[177,627,628,634,640],{},[180,629,630,633],{},[51,631,632],{},"掌控绝对入口","：Android 与 Chrome 触达全球数十亿用户",[180,635,636,639],{},[51,637,638],{},"本地化秒级响应","：将精简开源模型原生植入系统，用户无需联网、无需支付 API 费用",[180,641,642,645],{},[51,643,644],{},"隐私与安全","：数据不出设备，天然满足隐私法规",[10,647,648],{},"精简模型赢得了终端，就赢得了最广阔的消费级市场。",[63,650,652],{"id":651},"三联合-intel-与-amd组建反-nvidia-算力联盟","三、联合 Intel 与 AMD：组建反 Nvidia 算力联盟",[10,654,655],{},"在云端，Nvidia 靠 GPU 和 CUDA 打造了极其顽固的算力垄断；OpenAI 模式让全行业都沦为 Nvidia 的\"租客\"。Google 仅靠 TPU 孤军奋战，依然是在对方的规则里打仗。",[10,657,658],{},"破局的关键在于把视角从云端投向端侧，与 Intel 和 AMD 结成深度的软硬一体战略联盟：",[177,660,661,666,671],{},[180,662,663],{},[51,664,665],{},"Intel 与 AMD 控制着全球主流的 CPU 和新一代 NPU 生态",[180,667,668],{},[51,669,670],{},"Google 将精简开源模型针对 Intel NPU 与 AMD Ryzen AI\u002FROCm 做底层深度优化",[180,672,673],{},[51,674,675],{},"实现零门槛本地运行，绕过高昂的 GPU 门槛",[10,677,678],{},"当\"Google 开源模型 + Intel\u002FAMD 芯片\"成为 AI PC 的出厂标配，全球数以亿计的终端设备就会变成 Google 生态的繁衍土壤。",[37,680,682],{"id":681},"为什么-google-现在如此犹豫","为什么 Google 现在如此犹豫",[10,684,685],{},"既然开源生态是 Google 的基因，为什么它走得束手束脚？三个原因：",[333,687,688,694,700],{},[180,689,690,693],{},[51,691,692],{},"财务上的沉没成本","：训练千亿级顶尖模型需要数亿美元。在华尔街季报的压力下，管理层极难下定决心把最顶级的模型免费开源",[180,695,696,699],{},[51,697,698],{},"安全的责任枷锁","：作为巨头，Google 一旦开源了被滥用的顶级模型，面临的监管问责和舆情风险远高于创业公司",[180,701,702,705],{},[51,703,704],{},"内部的战略撕扯","：在\"用闭源模型守护搜索广告基本盘\"和\"彻底开源重构云生态\"之间，Google 至今没有做出真正的抉择",[37,707,708],{"id":708},"结语",[10,710,711],{},"OpenAI 只是 AI 演进初期的一段插曲，绝非产业发展的终局范式。",[10,713,714,715,718],{},"从\"盲目追赶闭源 API\"转向 ",[51,716,717],{},"\"开源顶级模型 + 精简模型占领终端 + 联合硬件巨头赋能生态 + GCP 收割算力底座\"","——这不仅是 Google 历史基因的复归，更是其告别\"柯达时刻\"的唯一通途。",[10,720,721],{},"放下面子，打破传统范式，重新拥抱开发者与硬件盟友——那个曾经无往不胜的 Google，就能再次按自己的节奏改写时代规则。",[28,723],{},[10,725,726],{},[24,727,728,729,732],{},"这篇文章是对 Google 战略困境的个人观察与思考。如果你对全栈开发或 AI 应用落地有兴趣，欢迎",[378,730,731],{"href":380},"聊聊","。",{"title":734,"searchDepth":735,"depth":735,"links":736},"",2,[737,738,744,745,750,751,752,753,758,759,764,765],{"id":39,"depth":735,"text":40},{"id":57,"depth":735,"text":58,"children":739},[740,742,743],{"id":65,"depth":741,"text":66},3,{"id":133,"depth":741,"text":134},{"id":157,"depth":741,"text":158},{"id":164,"depth":735,"text":165},{"id":206,"depth":735,"text":207,"children":746},[747,748,749],{"id":210,"depth":741,"text":211},{"id":259,"depth":741,"text":260},{"id":297,"depth":741,"text":298},{"id":327,"depth":735,"text":328},{"id":355,"depth":735,"text":356},{"id":409,"depth":735,"text":410},{"id":426,"depth":735,"text":427,"children":754},[755,756,757],{"id":433,"depth":741,"text":434},{"id":494,"depth":741,"text":495},{"id":516,"depth":741,"text":517},{"id":523,"depth":735,"text":524},{"id":560,"depth":735,"text":561,"children":760},[761,762,763],{"id":564,"depth":741,"text":565},{"id":613,"depth":741,"text":614},{"id":651,"depth":741,"text":652},{"id":681,"depth":735,"text":682},{"id":708,"depth":735,"text":708},"tech","2026-08-10","A deep comparison between Google's current AI dilemma and Kodak's historic downfall — both invented the future but were trapped by their cash cows. The way out isn't becoming the next OpenAI, but returning to Google's open-source DNA.",false,"md",{},true,"\u002Fblogs\u002Fgoogle-kodak-moment-open-source-strategy",null,{"title":5,"description":768},"blogs\u002Fgoogle-kodak-moment-open-source-strategy",[778,779,780,781,782],"google","ai","open-source","strategy","opinion","niIUlN3IpS9KsLbaPvKHmY6Xl-IUyHtanX5Nbgw6nHg",{"prev":774,"next":785},{"id":786,"title":787,"body":788,"category":766,"cover":2275,"date":2276,"description":2277,"draft":769,"extension":770,"meta":2278,"navigation":772,"path":2279,"readingTime":774,"seo":2280,"stem":2281,"tags":2282,"__hash__":2291},"blogs\u002Fblogs\u002Fai-native-simulation-first-bilingual.md","AI-Native Software Engineering: Let the System Run Virtually Before Writing the First Line of Code",{"type":7,"value":789,"toc":2253},[790,819,825,827,831,834,844,851,854,871,877,880,884,890,897,903,910,913,918,921,925,931,934,937,942,947,950,956,971,975,978,984,990,996,1208,1214,1218,1221,1227,1247,1260,1265,1276,1280,1286,1292,1298,1304,1319,1326,1333,1337,1343,1346,1352,1359,1362,1394,1401,1406,1410,1413,1419,1425,1435,1445,1451,1455,1458,1464,1467,1473,1479,1485,1491,1495,1501,1504,1518,1525,1531,1534,1540,1542,1547,1549,1551,1555,1583,1589,1591,1595,1598,1604,1611,1614,1631,1637,1640,1644,1650,1657,1663,1670,1673,1678,1681,1685,1691,1694,1697,1702,1707,1710,1716,1731,1735,1738,1744,1750,1756,1917,1923,1927,1930,1936,1956,1967,1972,1983,1987,1993,1999,2005,2011,2022,2029,2036,2040,2046,2049,2055,2062,2065,2097,2104,2109,2113,2116,2122,2128,2138,2147,2153,2157,2160,2166,2169,2175,2181,2187,2193,2197,2203,2206,2220,2227,2233,2236,2242,2244,2249],[18,791,792,814],{},[10,793,794,797,798,801,802,805,806,809,810,813],{},[51,795,796],{},"Core idea:"," Future software development will not revolve around documents, nor around code, but around a ",[51,799,800],{},"Dynamic Project Tree",". Ideas are captured by voice and grow into a tree-shaped knowledge base; every node is first implemented as a ",[51,803,804],{},"virtual function","; virtual functions are wired along the tree into a ",[51,807,808],{},"virtual system","; ",[51,811,812],{},"data-flow simulation"," runs on that virtual system; and only after every simulation passes does real programming begin.",[10,815,816],{},[51,817,818],{},"Code is Output. Model is Truth. Voice is the Beginning. Simulation is the Proof.",[18,820,821],{},[10,822,22,823],{},[24,824,26],{},[28,826],{},[37,828,830],{"id":829},"_1-ai-writes-code-faster-and-faster-software-isnt-getting-faster","1. AI writes code faster and faster — software isn't getting faster",[10,832,833],{},"Today's mainstream AI coding tools — Copilot, Codex, Claude Code — are all essentially embedded in a pipeline designed decades ago:",[835,836,841],"pre",{"className":837,"code":839,"language":840},[838],"language-text","Requirements → Documents → Prototype → Development → Testing → Deployment\n","text",[842,843,839],"code",{"__ignoreMap":734},[10,845,846,847,850],{},"That pipeline was born in an era ",[51,848,849],{},"without AI",". AI was simply plugged into the \"development\" stage, making the code-writing step faster.",[10,852,853],{},"But any engineer who has shipped a real project knows that writing code was never the slowest part. What actually burns time is:",[177,855,856,859,862,865,868],{},[180,857,858],{},"Requirements churn early on; you finish the code only to discover you understood them wrong",[180,860,861],{},"Architectural changes ripple everywhere, and the cost of change grows exponentially with progress",[180,863,864],{},"Documentation forever lags the code, and nobody trusts it",[180,866,867],{},"Multiple AI agents each read the code on their own, with no shared understanding of the project",[180,869,870],{},"Critical design rationale lives scattered across meetings, chat logs, and someone's head",[10,872,873,874],{},"Making the \"write code\" step ten times faster helps with none of these. ",[51,875,876],{},"Errors still stay hidden until integration, joint debugging, or production — and by then, the cost of fixing them has grown by orders of magnitude.",[10,878,879],{},"So what truly deserves to be rebuilt is not the AI. It's the software engineering process itself.",[37,881,883],{"id":882},"_2-hardware-answered-this-long-ago-nobody-tapes-out-without-simulation","2. Hardware answered this long ago: nobody tapes out without simulation",[10,885,886,887],{},"The chip industry has an iron law: ",[51,888,889],{},"you must simulate before tape-out.",[10,891,892,893,896],{},"A single tape-out costs millions of dollars and months of lead time. No team would dare send an unverified design to the fab. That's why the heart of the EDA toolchain has never been \"draw circuits faster\" — it is: make the entire chip ",[51,894,895],{},"run"," in a virtual environment first. Timing, power, signal integrity — everything is verified in the virtual world before anything enters the physical one.",[10,898,899,900,382],{},"Now look at software: we essentially ",[51,901,902],{},"tape out naked",[10,904,905,906,909],{},"The requirements document gets written (or not even finished), real code starts immediately, and then integration and testing are left to slam every design error out in the \"physical world.\" We tolerate this only because software's \"re-tape-out\" looks cheap — just change the code, right? But in the AI era, when agents can generate tens of thousands of lines overnight, ",[51,907,908],{},"the cost of rework is precisely what gets amplified",": if the direction is wrong, the faster you generate, the more you waste.",[10,911,912],{},"AI-era software engineering should converge toward hardware engineering:",[10,914,915],{},[51,916,917],{},"Build the virtual system first → complete simulation and verification → then do the real implementation.",[10,919,920],{},"That is the full process this article lays out.",[37,922,924],{"id":923},"_3-voice-is-the-first-input-thought-capture-not-faster-typing","3. Voice is the first input: thought capture, not faster typing",[10,926,927,928,382],{},"The process does not start with a document. It starts with ",[51,929,930],{},"speaking",[10,932,933],{},"Human thinking is not linear. Insights arrive in a flash: a feature idea while walking, the realization in the shower that two modules' dependency is backwards. If capturing that moment requires opening Word, recalling a template, and composing sentences, the thought is long gone.",[10,935,936],{},"The value of voice is not input speed. It is this:",[10,938,939],{},[51,940,941],{},"It captures the genuine ideas inside a thought process with the lowest possible friction.",[18,943,944],{},[10,945,946],{},"Voice = Thought Capture",[10,948,949],{},"The future starting point of development looks like this:",[835,951,954],{"className":952,"code":953,"language":840},[838],"An idea occurs\n    ↓\nSay it out loud (Voice)\n    ↓\nAI understands and structures it\n    ↓\nAutomatically mounted onto \u002F updates the project tree\n",[842,955,953],{"__ignoreMap":734},[10,957,958,959,962,963,966,967,970],{},"You say: \"Sharing should support QR codes, and the codes need a configurable expiry.\" The AI understands, creates a ",[842,960,961],{},"QR code"," child node under the ",[842,964,965],{},"Sharing"," node of the project tree, and records the \"supports expiry\" constraint in its properties — along with ",[51,968,969],{},"the context in which you said it",". Three months later nobody has to excavate chat history; the full lineage of the decision lives on the tree.",[37,972,974],{"id":973},"_4-a-tree-shaped-knowledge-base-the-dynamic-project-tree","4. A tree-shaped knowledge base: the Dynamic Project Tree",[10,976,977],{},"Why a tree? Because the human mental model of a project naturally is one:",[835,979,982],{"className":980,"code":981,"language":840},[838],"Project\n├── Users\n│     ├── Login\n│     ├── Permissions\n│     └── Profile\n├── Sharing\n│     ├── QR code\n│     ├── Links\n│     └── Access control\n├── AI capabilities\n│     ├── Poster generation\n│     ├── OCR\n│     └── Copywriting\n└── Data\n      ├── Database\n      ├── API\n      └── Cache\n",[842,983,981],{"__ignoreMap":734},[10,985,986,987,382],{},"Ideas keep sprouting new nodes, rearranging relationships, pruning dead branches. The truth of a project should not live in a Word document that goes stale in a week — it should be this ",[51,988,989],{},"living tree",[10,991,992,993,175],{},"The essential difference from a traditional requirements document: each node on the tree is not a paragraph of prose, but a ",[51,994,995],{},"structured data object",[835,997,1001],{"className":998,"code":999,"language":1000,"meta":734,"style":734},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","node: Sharing\u002FQR code\ndescription: Generate expiring QR codes for shared content\nstatus: simulated        # idea → defined → simulated → implemented → verified\nowner: harry\ndepends_on: [Users\u002FPermissions, Data\u002FAPI]\ninterface:\n  input:  { content_id: string, ttl_hours: int }\n  output: { qr_url: string, expires_at: datetime }\nconstraints:\n  - Maximum validity is 72 hours\n  - Accessing after expiry returns 410\nhistory:\n  - 2026-07-12: Created via voice input, \"sharing should support QR codes\"\n  - 2026-07-14: Expiry constraint added (decided after discussion)\n","yaml",[842,1002,1003,1019,1029,1043,1054,1077,1086,1118,1148,1156,1165,1173,1181,1195],{"__ignoreMap":734},[1004,1005,1008,1012,1015],"span",{"class":1006,"line":1007},"line",1,[1004,1009,1011],{"class":1010},"swJcz","node",[1004,1013,175],{"class":1014},"sMK4o",[1004,1016,1018],{"class":1017},"sfazB"," Sharing\u002FQR code\n",[1004,1020,1021,1024,1026],{"class":1006,"line":735},[1004,1022,1023],{"class":1010},"description",[1004,1025,175],{"class":1014},[1004,1027,1028],{"class":1017}," Generate expiring QR codes for shared content\n",[1004,1030,1031,1034,1036,1039],{"class":1006,"line":741},[1004,1032,1033],{"class":1010},"status",[1004,1035,175],{"class":1014},[1004,1037,1038],{"class":1017}," simulated",[1004,1040,1042],{"class":1041},"sHwdD","        # idea → defined → simulated → implemented → verified\n",[1004,1044,1046,1049,1051],{"class":1006,"line":1045},4,[1004,1047,1048],{"class":1010},"owner",[1004,1050,175],{"class":1014},[1004,1052,1053],{"class":1017}," harry\n",[1004,1055,1057,1060,1062,1065,1068,1071,1074],{"class":1006,"line":1056},5,[1004,1058,1059],{"class":1010},"depends_on",[1004,1061,175],{"class":1014},[1004,1063,1064],{"class":1014}," [",[1004,1066,1067],{"class":1017},"Users\u002FPermissions",[1004,1069,1070],{"class":1014},",",[1004,1072,1073],{"class":1017}," Data\u002FAPI",[1004,1075,1076],{"class":1014},"]\n",[1004,1078,1080,1083],{"class":1006,"line":1079},6,[1004,1081,1082],{"class":1010},"interface",[1004,1084,1085],{"class":1014},":\n",[1004,1087,1089,1092,1094,1097,1100,1102,1105,1107,1110,1112,1115],{"class":1006,"line":1088},7,[1004,1090,1091],{"class":1010},"  input",[1004,1093,175],{"class":1014},[1004,1095,1096],{"class":1014},"  {",[1004,1098,1099],{"class":1010}," content_id",[1004,1101,175],{"class":1014},[1004,1103,1104],{"class":1017}," string",[1004,1106,1070],{"class":1014},[1004,1108,1109],{"class":1010}," ttl_hours",[1004,1111,175],{"class":1014},[1004,1113,1114],{"class":1017}," int",[1004,1116,1117],{"class":1014}," }\n",[1004,1119,1121,1124,1126,1129,1132,1134,1136,1138,1141,1143,1146],{"class":1006,"line":1120},8,[1004,1122,1123],{"class":1010},"  output",[1004,1125,175],{"class":1014},[1004,1127,1128],{"class":1014}," {",[1004,1130,1131],{"class":1010}," qr_url",[1004,1133,175],{"class":1014},[1004,1135,1104],{"class":1017},[1004,1137,1070],{"class":1014},[1004,1139,1140],{"class":1010}," expires_at",[1004,1142,175],{"class":1014},[1004,1144,1145],{"class":1017}," datetime",[1004,1147,1117],{"class":1014},[1004,1149,1151,1154],{"class":1006,"line":1150},9,[1004,1152,1153],{"class":1010},"constraints",[1004,1155,1085],{"class":1014},[1004,1157,1159,1162],{"class":1006,"line":1158},10,[1004,1160,1161],{"class":1014},"  -",[1004,1163,1164],{"class":1017}," Maximum validity is 72 hours\n",[1004,1166,1168,1170],{"class":1006,"line":1167},11,[1004,1169,1161],{"class":1014},[1004,1171,1172],{"class":1017}," Accessing after expiry returns 410\n",[1004,1174,1176,1179],{"class":1006,"line":1175},12,[1004,1177,1178],{"class":1010},"history",[1004,1180,1085],{"class":1014},[1004,1182,1184,1186,1190,1192],{"class":1006,"line":1183},13,[1004,1185,1161],{"class":1014},[1004,1187,1189],{"class":1188},"sTEyZ"," 2026-07-12",[1004,1191,175],{"class":1014},[1004,1193,1194],{"class":1017}," Created via voice input, \"sharing should support QR codes\"\n",[1004,1196,1198,1200,1203,1205],{"class":1006,"line":1197},14,[1004,1199,1161],{"class":1014},[1004,1201,1202],{"class":1188}," 2026-07-14",[1004,1204,175],{"class":1014},[1004,1206,1207],{"class":1017}," Expiry constraint added (decided after discussion)\n",[10,1209,1210,1211],{},"A node carries its description, status, owner, dependencies, interface contract, constraints, and evolution history. The whole tree is a continuously growing knowledge graph of the project — it is the requirements base, the architecture diagram, the interface documentation, and the decision log. ",[51,1212,1213],{},"It is the project's single source of truth.",[37,1215,1217],{"id":1216},"_5-the-key-step-every-node-becomes-a-virtual-function-first","5. The key step: every node becomes a \"virtual function\" first",[10,1219,1220],{},"This is the core of the methodology — and the sharpest break from \"using AI to write requirements docs.\"",[10,1222,1223,1224,175],{},"A feature node on the tree must not stop at \"a paragraph of description.\" Once a node's definition is reasonably clear, the AI immediately promotes it into a ",[51,1225,1226],{},"Virtual Function",[177,1228,1229,1235,1241],{},[180,1230,1231,1234],{},[51,1232,1233],{},"It has a real interface",": the input\u002Foutput schema is strictly defined — the very contract the future real implementation must honor",[180,1236,1237,1240],{},[51,1238,1239],{},"It has a virtual implementation",": no real logic inside; the AI generates a \"behaviorally believable\" mock from the node's description — legal input returns semantically plausible simulated output, illegal input errors according to the constraints",[180,1242,1243,1246],{},[51,1244,1245],{},"It can be called",": it is a genuinely runnable function\u002Fservice stub, not a box in a document",[10,1248,1249,1250,1252,1253,1256,1257,382],{},"Take the ",[842,1251,961],{}," node's virtual function: feed it ",[842,1254,1255],{},"{content_id: \"abc\", ttl_hours: 100}"," and it returns the error \"maximum validity is 72 hours\" — because the constraint is written on the node. Feed it legal parameters and it returns a structurally correct simulated ",[842,1258,1259],{},"qr_url",[10,1261,1262],{},[51,1263,1264],{},"Not one line of real business code exists, yet the feature already \"exists.\"",[10,1266,1267,1268,1271,1272,1275],{},"Engineers will find this familiar — it smells like a mock, a stub, the provider stub in contract testing. The difference: a traditional mock is an ",[51,1269,1270],{},"afterthought",", hand-maintained and disposable, written while testing code that already exists. Here, virtual functions are ",[51,1273,1274],{},"first-class citizens that precede the code"," — auto-generated by the AI from node definitions, auto-updated when definitions change, and — as the next section shows — wired together into a complete system.",[37,1277,1279],{"id":1278},"_6-along-the-tree-wire-virtual-functions-into-a-virtual-system","6. Along the tree, wire virtual functions into a virtual system",[10,1281,1282,1283],{},"A single virtual function is just a callable stub. The real power is this: ",[51,1284,1285],{},"the dependency edges on the tree are the system's wiring diagram.",[10,1287,1288,1289,1291],{},"Every node declares its ",[842,1290,1059],{}," and its interface contract, so the AI can walk those edges and assemble all the virtual functions:",[835,1293,1296],{"className":1294,"code":1295,"language":840},[838],"[Voice\u002FText] ──> Dynamic project tree ──> Virtual functions ──wired──> Virtual system\n                                                   │\n   Users\u002FLogin (virtual) ──> Users\u002FPermissions (virtual) ──> Sharing\u002FAccess control (virtual)\n                                                   │\n   Sharing\u002FQR code (virtual) \u003C── Data\u002FAPI (virtual) \u003C── Data\u002FDatabase (virtual)\n",[842,1297,1295],{"__ignoreMap":734},[10,1299,1300,1301,175],{},"What you now hold is a ",[51,1302,1303],{},"system with zero real code that nevertheless runs as a whole",[177,1305,1306,1309,1312],{},[180,1307,1308],{},"Every module can be called, behaving exactly as its node defines",[180,1310,1311],{},"Modules genuinely call each other along the dependencies declared on the tree",[180,1313,1314,1315,1318],{},"The entire call topology ",[24,1316,1317],{},"is"," the architecture of the future real system",[10,1320,1321,1322,1325],{},"It is the software system's ",[51,1323,1324],{},"digital twin"," — except the twin is born before the original.",[10,1327,1328,1329,1332],{},"At this stage, a mass of problems that traditionally surface only at integration time appear instantly: two nodes' interfaces don't line up, dependencies form a cycle, a module assumes a data field its upstream never produces. ",[51,1330,1331],{},"The fix is not editing code — it is editing the tree",": adjust the node definitions, virtual functions regenerate automatically, the system rewires itself. The cost of change is effectively zero.",[37,1334,1336],{"id":1335},"_7-data-flow-simulation-living-everyday-life-inside-the-virtual-system","7. Data-flow simulation: living everyday life inside the virtual system",[10,1338,1339,1340,382],{},"With the virtual system assembled, verification begins: ",[51,1341,1342],{},"Data Flow Simulation",[10,1344,1345],{},"The AI generates simulation scenarios from the project tree — in essence a batch of end-to-end user journeys with bulk synthetic data:",[835,1347,1350],{"className":1348,"code":1349,"language":840},[838],"Scenario 1: New user registers → logs in → creates content → shares via QR code → someone scans and visits\nScenario 2: Visiting after the QR code expires → must return 410\nScenario 3: Unauthorized user tries to open an access-controlled share → must be blocked\nScenario 4: 1,000 concurrent share requests → watch data flow across API \u002F Cache \u002F DB\n",[842,1351,1349],{"__ignoreMap":734},[10,1353,1354,1355,1358],{},"Synthetic data is injected at the system's entry points and genuinely flows through the virtual system. On the graph you can ",[51,1356,1357],{},"see"," how data travels: from the login node into permissions, from the API node into cache; where flow stops dead, where data gets dropped, which path nobody ever reaches, which node every path converges on.",[10,1360,1361],{},"The questions simulation answers are exactly the ones the traditional process answers latest and at the highest price:",[177,1363,1364,1370,1376,1382,1388],{},[180,1365,1366,1369],{},[51,1367,1368],{},"Does the business loop close?"," Can the user journey run start to finish?",[180,1371,1372,1375],{},[51,1373,1374],{},"Is the data complete?"," Does upstream actually produce every field downstream consumes?",[180,1377,1378,1381],{},[51,1379,1380],{},"Does the permission model leak?"," Is there any path that bypasses the permission node?",[180,1383,1384,1387],{},[51,1385,1386],{},"Is the architecture sound?"," Are dependency directions clean? Any accidental coupling or bottleneck nodes?",[180,1389,1390,1393],{},[51,1391,1392],{},"Were the failure paths considered?"," Expiry, failure, privilege escalation — does every error path have a destination?",[10,1395,1396,1397,1400],{},"Find a problem → edit the tree → virtual functions auto-update → re-simulate. This loop runs in ",[51,1398,1399],{},"minutes",", not \"one iteration.\" Product managers and engineers argue over the same living, flowing diagram instead of two mutually contradictory documents.",[10,1402,1403],{},[51,1404,1405],{},"When every simulation scenario passes, what you have verified is not code — it is the design itself.",[37,1407,1409],{"id":1408},"_8-only-after-simulation-passes-does-real-programming-begin","8. Only after simulation passes does real programming begin",[10,1411,1412],{},"Only now does real programming start. And \"programming\" at this point means something entirely different:",[10,1414,1415,1418],{},[51,1416,1417],{},"1. Contracts freeze."," Passing simulation means every node's interface contract, constraints, and dependencies have been verified. They freeze into the implementation baseline.",[10,1420,1421,1424],{},[51,1422,1423],{},"2. Node-by-node \"materialization.\""," AI agents claim nodes and replace virtual implementations with real ones — real databases, real algorithms, real third-party calls. The external interface does not change by a single byte.",[10,1426,1427,1430,1431,1434],{},[51,1428,1429],{},"3. Massive parallelism."," Because contracts are frozen, nodes are naturally decoupled: ten agents can materialize ten nodes simultaneously without blocking each other. One node not materialized yet? Fine — its virtual version still holds the line inside the system, which stays runnable at all times. This is hardware's ",[51,1432,1433],{},"mixed simulation",": real and virtual modules coexist, replaced incrementally.",[10,1436,1437,1440,1441,1444],{},[51,1438,1439],{},"4. Simulation scenarios become the tests."," Every scenario and dataset accumulated during simulation converts automatically into integration and regression tests. A real implementation must produce the same results under the same scenarios before it may be marked ",[842,1442,1443],{},"verified",". Tests are not written after implementation — they exist before it, as the acceptance standard.",[10,1446,1447,1450],{},[51,1448,1449],{},"5. Agents read the tree, not the code."," An agent picking up a task does not need to wade through hundreds of thousands of lines to guess design intent. It reads the project tree: current goal, node contract, dependencies, decision history, why it was designed this way. Code is merely this tree's projection at a moment in time.",[37,1452,1454],{"id":1453},"_9-why-this-is-the-highest-efficiency-path","9. Why this is the highest-efficiency path",[10,1456,1457],{},"Put the two processes side by side:",[835,1459,1462],{"className":1460,"code":1461,"language":840},[838],"Traditional process:\n  Documents (static, quickly stale) → Coding → Design errors surface at integration → Massive rework\n  ─────────────── Errors surface at the most expensive stage ───────────────\n\nAI-native process:\n  Voice → Project tree → Virtual functions → Virtual system → Data-flow simulation → Contract freeze → Parallel materialization\n  ──────── Errors surface where change cost ≈ 0 ────────   ──── Code right the first time ────\n",[842,1463,1461],{"__ignoreMap":734},[10,1465,1466],{},"The efficiency advantage comes from four levers:",[10,1468,1469,1472],{},[51,1470,1471],{},"Errors shift left to the cheapest point."," Decades of software engineering data point at one fact: the later a defect is found, the more it costs — from requirements stage to production, the difference can be a hundredfold. Simulation drags integration-level and architecture-level errors back to the stage where \"tweaking the tree\" fixes them.",[10,1474,1475,1478],{},[51,1476,1477],{},"Coding turns from exploration into execution."," In traditional development, much coding is exploratory — you only learn whether the design works by writing it. After simulation passes, coding becomes execution of verified contracts, and that is precisely the kind of well-scoped, clear-boundary task AI agents are best at. Fast generation plus low rework is where the speed advantage actually cashes out.",[10,1480,1481,1484],{},[51,1482,1483],{},"Parallelism is guaranteed by the architecture."," Contract-first makes nodes independently materializable; mixed running keeps the system demonstrable and runnable at every moment.",[10,1486,1487,1490],{},[51,1488,1489],{},"The cost of understanding approaches zero."," Humans and all agents share one tree. A new member — human or agent — doesn't need \"three months to learn the codebase\"; reading the tree suffices. And requirements docs, interface docs, test docs are all generated from the tree — documentation is no longer where work begins, but what work outputs.",[37,1492,1494],{"id":1493},"_10-the-complete-flow-and-the-vision","10. The complete flow, and the vision",[835,1496,1499],{"className":1497,"code":1498,"language":840},[838],"Idea (Voice)\n    ↓\nAI understanding & structuring\n    ↓\nDynamic project tree (tree-shaped knowledge base)\n    ↓\nNode → Virtual function (interface contract + AI-generated mock behavior)\n    ↓\nWire along the tree → Virtual system (the system's digital twin)\n    ↓\nData-flow simulation (all end-to-end scenarios pass)\n    ↓\nHuman sign-off, contract freeze\n    ↓\nAgents materialize in parallel (virtual → real, node by node)\n    ↓\nSimulation scenarios → automated tests → automated deployment\n",[842,1500,1498],{"__ignoreMap":734},[10,1502,1503],{},"In this paradigm, the developer's center of gravity shifts completely:",[177,1505,1506,1512],{},[180,1507,1508,1511],{},[51,1509,1510],{},"Humans",": generate ideas, make decisions, scrutinize the design inside the simulation, confirm direction",[180,1513,1514,1517],{},[51,1515,1516],{},"AI",": captures thought, maintains the project tree, generates virtual functions, runs simulations, materializes code, verifies results",[10,1519,1520,1521,1524],{},"Software development stops being \"writing code\" and becomes ",[51,1522,1523],{},"cultivating a continuously growing digital model of the project",". The dynamic project tree is not merely a requirements tool — it is the project's digital organism. Code, docs, tests, interfaces are just the forms it automatically takes at different stages.",[10,1526,1527,1528],{},"The chip industry spent thirty years proving one thing: ",[51,1529,1530],{},"making the system run in the virtual world first is the fastest road to the physical one.",[10,1532,1533],{},"It's time the software industry caught up on that lesson.",[18,1535,1536],{},[10,1537,1538],{},[51,1539,818],{},[28,1541],{},[10,1543,1544],{},[24,1545,1546],{},"This is a v0.2 draft — discussion welcome.",[28,1548],{},[28,1550],{},[388,1552,1554],{"id":1553},"ai-native-软件工程先让系统虚拟地跑起来再写第一行代码","AI Native 软件工程：先让系统「虚拟地跑起来」，再写第一行代码",[18,1556,1557,1579],{},[10,1558,1559,1562,1563,1570,1571,1574,1575,1578],{},[51,1560,1561],{},"核心思想","：未来的软件开发，不以文档为中心，也不以代码为中心，而是以一棵",[51,1564,1565,1566,1569],{},"动态项目树（Dynamic Project Tree）",[51,1567,1568],{},"为中心。语音录入想法，长成树形知识库；每个节点先实现为","虚拟功能","；虚拟功能沿着树连接成一个",[51,1572,1573],{},"虚拟系统","；在虚拟系统上完成",[51,1576,1577],{},"数据流仿真","；仿真全部跑通之后，才开始真实的编程。",[10,1580,1581],{},[51,1582,818],{},[18,1584,1585],{},[10,1586,22,1587],{},[24,1588,398],{},[28,1590],{},[37,1592,1594],{"id":1593},"一ai-写代码越来越快软件却没有变快","一、AI 写代码越来越快，软件却没有变快",[10,1596,1597],{},"目前主流的 AI 编程工具——Copilot、Codex、Claude Code——本质上都嵌在一条几十年前设计的流水线里：",[835,1599,1602],{"className":1600,"code":1601,"language":840},[838],"需求 → 文档 → 原型 → 开发 → 测试 → 部署\n",[842,1603,1601],{"__ignoreMap":734},[10,1605,1606,1607,1610],{},"这条流水线诞生于",[51,1608,1609],{},"没有 AI 的时代","。AI 只是被插进了「开发」这一环，让写代码这一步变快了。",[10,1612,1613],{},"但任何做过真实项目的工程师都知道，写代码从来不是最慢的环节。真正消耗时间的是：",[177,1615,1616,1619,1622,1625,1628],{},[180,1617,1618],{},"需求在前期反复变化，代码写完才发现理解错了",[180,1620,1621],{},"架构调整牵一发动全身，改动成本随进度指数上升",[180,1623,1624],{},"文档永远落后于代码，没人相信文档",[180,1626,1627],{},"多个 AI Agent 各自读代码，对项目没有统一理解",[180,1629,1630],{},"关键的设计思路散落在会议、聊天记录和某个人的脑子里",[10,1632,1633,1634],{},"把「写代码」这一步加速十倍，对上面这些问题的帮助是零。",[51,1635,1636],{},"错误依然要等到集成、联调、上线才暴露，而那时修复成本已经涨了几个数量级。",[10,1638,1639],{},"所以真正值得重构的不是 AI，而是整个软件工程流程本身。",[37,1641,1643],{"id":1642},"二硬件行业早就给出了答案没有人不经仿真就流片","二、硬件行业早就给出了答案：没有人不经仿真就流片",[10,1645,1646,1647],{},"芯片行业有一条铁律：",[51,1648,1649],{},"流片之前，必须仿真。",[10,1651,1652,1653,1656],{},"一次流片动辄数百万美元、数月周期，没有任何团队敢把没有仿真验证过的设计直接送去工厂。所以 EDA 工具链的核心从来不是「画电路更快」，而是：先在虚拟环境里把整个芯片",[51,1654,1655],{},"跑起来","——时序、功耗、信号完整性，全部在虚拟世界里验证通过，才进入物理世界。",[10,1658,1659,1660,732],{},"再看软件行业：我们几乎是",[51,1661,1662],{},"裸奔着直接「流片」",[10,1664,1665,1666,1669],{},"需求文档写完（甚至没写完），就开始写真实代码，然后靠联调和测试在「物理世界」里撞出所有设计错误。我们容忍这种做法，只是因为软件的「重新流片」成本看起来低——改代码就好了嘛。但在 AI 时代，当 Agent 可以一夜之间生成数万行代码时，",[51,1667,1668],{},"返工的成本恰恰被放大了","：方向错了，生成得越快，浪费得越多。",[10,1671,1672],{},"AI 时代的软件工程，应该向硬件工程收敛：",[10,1674,1675],{},[51,1676,1677],{},"先构建虚拟系统 → 完成仿真验证 → 再进行真实实现。",[10,1679,1680],{},"这就是本文要展开的完整流程。",[37,1682,1684],{"id":1683},"三语音是第一输入思维采集而不是打字提速","三、语音是第一输入：思维采集，而不是打字提速",[10,1686,1687,1688,732],{},"流程的起点不是文档，而是",[51,1689,1690],{},"说话",[10,1692,1693],{},"人的想法不是线性的，灵感往往在一瞬间产生：走路时想到一个功能点、洗澡时意识到两个模块的依赖关系反了。如果此刻需要打开 Word、回忆模板、组织措辞，思路早就断了。",[10,1695,1696],{},"语音的价值不在于输入速度，而在于：",[10,1698,1699],{},[51,1700,1701],{},"它能以最低的摩擦，捕捉思考过程中的真实想法。",[18,1703,1704],{},[10,1705,1706],{},"Voice = Thought Capture（思维采集）",[10,1708,1709],{},"未来的开发起点是这样的：",[835,1711,1714],{"className":1712,"code":1713,"language":840},[838],"想到一个想法\n    ↓\n直接说出来（Voice）\n    ↓\nAI 理解、结构化\n    ↓\n自动挂载 \u002F 更新到项目树\n",[842,1715,1713],{"__ignoreMap":734},[10,1717,1718,1719,1722,1723,1726,1727,1730],{},"你说：「分享功能要支持二维码，而且要能设置有效期。」AI 听懂后，在项目树的 ",[842,1720,1721],{},"分享"," 节点下新建 ",[842,1724,1725],{},"二维码"," 子节点，并在其属性里记录「支持有效期」这条约束——同时记下",[51,1728,1729],{},"你是在什么上下文里说这句话的","。三个月后没有人需要考古聊天记录，决策的来龙去脉就长在树上。",[37,1732,1734],{"id":1733},"四树形知识库动态项目树","四、树形知识库：动态项目树",[10,1736,1737],{},"为什么是树？因为人对项目的心智模型天然就是一棵树：",[835,1739,1742],{"className":1740,"code":1741,"language":840},[838],"Project\n├── 用户\n│     ├── 登录\n│     ├── 权限\n│     └── Profile\n├── 分享\n│     ├── 二维码\n│     ├── 链接\n│     └── 权限控制\n├── AI 能力\n│     ├── 海报生成\n│     ├── OCR\n│     └── 文案\n└── 数据\n      ├── 数据库\n      ├── API\n      └── Cache\n",[842,1743,1741],{"__ignoreMap":734},[10,1745,1746,1747,732],{},"想法不断长出新节点、调整节点关系、剪掉废弃分支。项目的真相不该保存在一份很快过时的 Word 文档里，而应该是这棵",[51,1748,1749],{},"活着的树",[10,1751,1752,1753,534],{},"和传统需求文档的本质区别在于：树上的每个节点不是一段自然语言描述，而是一个",[51,1754,1755],{},"结构化的数据对象",[835,1757,1759],{"className":998,"code":1758,"language":1000,"meta":734,"style":734},"node: 分享\u002F二维码\ndescription: 为分享内容生成带有效期的二维码\nstatus: simulated        # idea → defined → simulated → implemented → verified\nowner: harry\ndepends_on: [用户\u002F权限, 数据\u002FAPI]\ninterface:\n  input:  { content_id: string, ttl_hours: int }\n  output: { qr_url: string, expires_at: datetime }\nconstraints:\n  - 有效期最长 72 小时\n  - 过期后访问返回 410\nhistory:\n  - 2026-07-12: 由语音输入创建，「分享要支持二维码」\n  - 2026-07-14: 增加有效期约束（讨论后决策）\n",[842,1760,1761,1770,1779,1789,1797,1815,1821,1845,1869,1875,1882,1889,1895,1906],{"__ignoreMap":734},[1004,1762,1763,1765,1767],{"class":1006,"line":1007},[1004,1764,1011],{"class":1010},[1004,1766,175],{"class":1014},[1004,1768,1769],{"class":1017}," 分享\u002F二维码\n",[1004,1771,1772,1774,1776],{"class":1006,"line":735},[1004,1773,1023],{"class":1010},[1004,1775,175],{"class":1014},[1004,1777,1778],{"class":1017}," 为分享内容生成带有效期的二维码\n",[1004,1780,1781,1783,1785,1787],{"class":1006,"line":741},[1004,1782,1033],{"class":1010},[1004,1784,175],{"class":1014},[1004,1786,1038],{"class":1017},[1004,1788,1042],{"class":1041},[1004,1790,1791,1793,1795],{"class":1006,"line":1045},[1004,1792,1048],{"class":1010},[1004,1794,175],{"class":1014},[1004,1796,1053],{"class":1017},[1004,1798,1799,1801,1803,1805,1808,1810,1813],{"class":1006,"line":1056},[1004,1800,1059],{"class":1010},[1004,1802,175],{"class":1014},[1004,1804,1064],{"class":1014},[1004,1806,1807],{"class":1017},"用户\u002F权限",[1004,1809,1070],{"class":1014},[1004,1811,1812],{"class":1017}," 数据\u002FAPI",[1004,1814,1076],{"class":1014},[1004,1816,1817,1819],{"class":1006,"line":1079},[1004,1818,1082],{"class":1010},[1004,1820,1085],{"class":1014},[1004,1822,1823,1825,1827,1829,1831,1833,1835,1837,1839,1841,1843],{"class":1006,"line":1088},[1004,1824,1091],{"class":1010},[1004,1826,175],{"class":1014},[1004,1828,1096],{"class":1014},[1004,1830,1099],{"class":1010},[1004,1832,175],{"class":1014},[1004,1834,1104],{"class":1017},[1004,1836,1070],{"class":1014},[1004,1838,1109],{"class":1010},[1004,1840,175],{"class":1014},[1004,1842,1114],{"class":1017},[1004,1844,1117],{"class":1014},[1004,1846,1847,1849,1851,1853,1855,1857,1859,1861,1863,1865,1867],{"class":1006,"line":1120},[1004,1848,1123],{"class":1010},[1004,1850,175],{"class":1014},[1004,1852,1128],{"class":1014},[1004,1854,1131],{"class":1010},[1004,1856,175],{"class":1014},[1004,1858,1104],{"class":1017},[1004,1860,1070],{"class":1014},[1004,1862,1140],{"class":1010},[1004,1864,175],{"class":1014},[1004,1866,1145],{"class":1017},[1004,1868,1117],{"class":1014},[1004,1870,1871,1873],{"class":1006,"line":1150},[1004,1872,1153],{"class":1010},[1004,1874,1085],{"class":1014},[1004,1876,1877,1879],{"class":1006,"line":1158},[1004,1878,1161],{"class":1014},[1004,1880,1881],{"class":1017}," 有效期最长 72 小时\n",[1004,1883,1884,1886],{"class":1006,"line":1167},[1004,1885,1161],{"class":1014},[1004,1887,1888],{"class":1017}," 过期后访问返回 410\n",[1004,1890,1891,1893],{"class":1006,"line":1175},[1004,1892,1178],{"class":1010},[1004,1894,1085],{"class":1014},[1004,1896,1897,1899,1901,1903],{"class":1006,"line":1183},[1004,1898,1161],{"class":1014},[1004,1900,1189],{"class":1188},[1004,1902,175],{"class":1014},[1004,1904,1905],{"class":1017}," 由语音输入创建，「分享要支持二维码」\n",[1004,1907,1908,1910,1912,1914],{"class":1006,"line":1197},[1004,1909,1161],{"class":1014},[1004,1911,1202],{"class":1188},[1004,1913,175],{"class":1014},[1004,1915,1916],{"class":1017}," 增加有效期约束（讨论后决策）\n",[10,1918,1919,1920],{},"节点带着描述、状态、负责人、依赖、接口契约、约束条件和演化历史。整棵树就是一张持续生长的项目知识图谱——它是需求库，是架构图，是接口文档，也是决策日志。",[51,1921,1922],{},"它是项目唯一的真相来源（Single Source of Truth）。",[37,1924,1926],{"id":1925},"五关键一步每个节点先做成虚拟功能","五、关键一步：每个节点先做成「虚拟功能」",[10,1928,1929],{},"这是整个方法论的核心，也是与「用 AI 写需求文档」最大的分野。",[10,1931,1932,1933,534],{},"树上的功能节点，不能只停留在「一段描述」。当一个节点的定义基本清晰后，AI 立刻把它升级为一个",[51,1934,1935],{},"虚拟功能（Virtual Function）",[177,1937,1938,1944,1950],{},[180,1939,1940,1943],{},[51,1941,1942],{},"有真实的接口","：输入输出 schema 是严格定义的，就是将来真实实现要遵守的契约",[180,1945,1946,1949],{},[51,1947,1948],{},"有虚拟的实现","：内部不写真实逻辑，由 AI 根据节点描述生成一个「行为逼真」的 mock——收到合法输入返回符合业务语义的模拟输出，收到非法输入按约束报错",[180,1951,1952,1955],{},[51,1953,1954],{},"可以被调用","：它是一个真正能跑的函数\u002F服务桩，而不是文档里的一个方框",[10,1957,1958,1959,1961,1962,1964,1965,732],{},"比如 ",[842,1960,1725],{}," 节点的虚拟功能：输入 ",[842,1963,1255],{},"，它会返回错误「有效期最长 72 小时」——因为约束就写在节点上。输入合法参数，它返回一个结构正确的模拟 ",[842,1966,1259],{},[10,1968,1969],{},[51,1970,1971],{},"没有一行真实业务代码，但这个功能已经「存在」了。",[10,1973,1974,1975,1978,1979,1982],{},"工程师对这个东西并不陌生——它像 mock，像 stub，像契约测试里的 provider stub。区别在于：传统 mock 是为已有代码写测试时的",[51,1976,1977],{},"附属品","，是手工维护、随手即弃的；而这里的虚拟功能是",[51,1980,1981],{},"先于代码存在的一等公民","，由 AI 从节点定义自动生成、随节点定义自动更新，并且——下一节会讲到——它们要被连接起来，组成一个完整的系统。",[37,1984,1986],{"id":1985},"六沿着树把虚拟功能连接成一个虚拟系统","六、沿着树，把虚拟功能连接成一个虚拟系统",[10,1988,1989,1990],{},"单个虚拟功能只是一个可调用的桩。真正的威力在于：",[51,1991,1992],{},"树上的依赖关系，就是系统的接线图。",[10,1994,1995,1996,1998],{},"每个节点都声明了 ",[842,1997,1059],{}," 和接口契约，AI 就可以沿着这些边，把所有虚拟功能组装起来：",[835,2000,2003],{"className":2001,"code":2002,"language":840},[838],"[语音\u002F文本] ──> 动态项目树 ──> 虚拟功能 ──连接──> 虚拟系统\n                                              │\n   用户\u002F登录（虚拟）──> 用户\u002F权限（虚拟）──> 分享\u002F权限控制（虚拟）\n                                              │\n   分享\u002F二维码（虚拟）\u003C── 数据\u002FAPI（虚拟）\u003C── 数据\u002F数据库（虚拟）\n",[842,2004,2002],{"__ignoreMap":734},[10,2006,2007,2008,534],{},"这时你得到的，是一个",[51,2009,2010],{},"没有任何真实代码、但整体可以运行的系统",[177,2012,2013,2016,2019],{},[180,2014,2015],{},"每个模块都能被调用，行为符合各自节点的定义",[180,2017,2018],{},"模块之间按照树上声明的依赖真实地互相调用",[180,2020,2021],{},"整个调用拓扑，就是未来真实系统的架构",[10,2023,2024,2025,2028],{},"它相当于整个软件系统的",[51,2026,2027],{},"数字孪生（Digital Twin）","——只不过孪生体先于本体出生。",[10,2030,2031,2032,2035],{},"在这一步，大量传统上要到联调阶段才暴露的问题会立刻现形：两个节点的接口对不上、依赖成环、某个模块假设的数据字段上游根本不产生。",[51,2033,2034],{},"修复方式不是改代码，而是改树","——调整节点定义，虚拟功能自动重新生成，系统重新连接。改动成本几乎为零。",[37,2037,2039],{"id":2038},"七数据流动仿真在虚拟系统上过日子","七、数据流动仿真：在虚拟系统上「过日子」",[10,2041,2042,2043,732],{},"虚拟系统搭好后，进入验证环节：",[51,2044,2045],{},"数据流动仿真（Data Flow Simulation）",[10,2047,2048],{},"AI 根据项目树生成仿真场景——本质上是一批端到端的用户旅程，配上批量模拟数据：",[835,2050,2053],{"className":2051,"code":2052,"language":840},[838],"场景 1: 新用户注册 → 登录 → 创建内容 → 生成二维码分享 → 他人扫码访问\n场景 2: 二维码过期后访问 → 应返回 410\n场景 3: 无权限用户尝试访问受控分享 → 应被拦截\n场景 4: 1000 个并发分享请求 → 观察数据在 API\u002FCache\u002FDB 间的流动\n",[842,2054,2052],{"__ignoreMap":734},[10,2056,2057,2058,2061],{},"模拟数据从系统入口注入，沿着虚拟系统真实地流动。你在图上",[51,2059,2060],{},"直观地看到","数据怎么走：从登录节点流向权限节点，从 API 节点流向缓存节点；哪里断流了，哪里数据被丢弃了，哪条路径根本没人走到，哪个节点成为所有路径的汇聚点。",[10,2063,2064],{},"仿真阶段要回答的问题，恰恰是传统流程里最晚、最贵才能回答的问题：",[177,2066,2067,2073,2079,2085,2091],{},[180,2068,2069,2072],{},[51,2070,2071],{},"业务闭环成立吗？"," 用户旅程能从头走到尾吗？",[180,2074,2075,2078],{},[51,2076,2077],{},"数据完备吗？"," 下游要用的字段，上游真的都产生了吗？",[180,2080,2081,2084],{},[51,2082,2083],{},"权限模型有漏洞吗？"," 有没有一条路径绕过了权限节点？",[180,2086,2087,2090],{},[51,2088,2089],{},"架构合理吗？"," 依赖方向是否清晰，有没有意外的耦合和瓶颈节点？",[180,2092,2093,2096],{},[51,2094,2095],{},"异常路径想过吗？"," 过期、失败、越权，每条错误路径都有归宿吗？",[10,2098,2099,2100,2103],{},"发现问题 → 修改树 → 虚拟功能自动更新 → 重新仿真。这个循环以",[51,2101,2102],{},"分钟","为单位，而不是以「一个迭代」为单位。产品经理和工程师看着同一张会流动的图讨论，而不是各自拿着两份互相矛盾的文档。",[10,2105,2106],{},[51,2107,2108],{},"当所有仿真场景全部通过时，你验证的不是代码，而是设计本身。",[37,2110,2112],{"id":2111},"八仿真通过才开始真实编程","八、仿真通过，才开始真实编程",[10,2114,2115],{},"到这一步，真实编程才开始。而此时的「编程」，已经和传统意义完全不同：",[10,2117,2118,2121],{},[51,2119,2120],{},"1. 契约冻结。"," 仿真通过意味着所有节点的接口契约、约束、依赖关系已被验证。它们被冻结为实现基线。",[10,2123,2124,2127],{},[51,2125,2126],{},"2. 逐节点「实化」。"," AI Agent 领取节点，把虚拟实现替换为真实实现——真实的数据库、真实的算法、真实的第三方调用。对外接口一个字节都不变。",[10,2129,2130,2133,2134,2137],{},[51,2131,2132],{},"3. 大规模并行。"," 因为契约已冻结，节点之间天然解耦：十个 Agent 可以同时实化十个节点，互不阻塞。一个节点还没实化完？没关系，它的虚拟版本仍在系统里顶着，整个系统始终可运行。这就是硬件仿真里的",[51,2135,2136],{},"混合仿真","——真实模块和虚拟模块共存，逐步替换。",[10,2139,2140,2143,2144,2146],{},[51,2141,2142],{},"4. 仿真场景直接变成测试。"," 仿真阶段积累的全部场景和数据，自动转化为集成测试和回归测试用例。真实实现必须在同样的场景下跑出同样的结果，才允许标记为 ",[842,2145,1443],{},"。测试不是实现后补写的，而是实现前就已存在的验收标准。",[10,2148,2149,2152],{},[51,2150,2151],{},"5. Agent 读树，不读代码。"," Agent 接到任务时，不需要通读几十万行代码去猜设计意图。它读取项目树：当前目标、节点契约、依赖关系、历史决策、为什么这样设计。代码只是这棵树在某个时刻的投影。",[37,2154,2156],{"id":2155},"九为什么说这是效率最高的路径","九、为什么说这是效率最高的路径",[10,2158,2159],{},"把两条流程放在一起看：",[835,2161,2164],{"className":2162,"code":2163,"language":840},[838],"传统流程:\n  文档（静态、易过时）→ 编码 → 联调时发现设计错误 → 大规模返工\n  ────────────────── 错误暴露在最贵的阶段 ──────────────────\n\nAI Native 流程:\n  语音 → 项目树 → 虚拟功能 → 虚拟系统 → 数据流仿真 → 契约冻结 → 并行实化\n  ──────── 错误暴露在改动成本≈0的阶段 ────────   ──── 编码一次成型 ────\n",[842,2165,2163],{"__ignoreMap":734},[10,2167,2168],{},"效率优势来自四个杠杆：",[10,2170,2171,2174],{},[51,2172,2173],{},"错误左移到成本最低点。"," 软件工程数十年的数据都指向同一个事实：缺陷发现得越晚，修复成本越高，从需求阶段到上线阶段可能相差百倍。仿真把集成级、架构级的错误全部拉到「改一改树」就能修复的阶段消化掉。",[10,2176,2177,2180],{},[51,2178,2179],{},"编码从探索变成执行。"," 传统开发中大量编码是探索性的——写了才知道设计行不行。仿真通过后，编码变成对已验证契约的执行，AI Agent 最擅长的恰恰是这种目标明确、边界清晰的任务。生成快、返工少，速度优势才真正兑现。",[10,2182,2183,2186],{},[51,2184,2185],{},"并行度由架构保证。"," 契约先行让节点天然可并行实化，混合运行让系统在任何时刻都保持可运行、可演示。",[10,2188,2189,2192],{},[51,2190,2191],{},"理解成本趋近于零。"," 人和所有 Agent 共享同一棵树。新成员（无论人还是 Agent）不需要「熟悉代码库三个月」，读树即可。而需求文档、接口文档、测试文档，全部从树上自动生成——文档不再是工作的开始，而是工作的输出。",[37,2194,2196],{"id":2195},"十完整流程与愿景","十、完整流程与愿景",[835,2198,2201],{"className":2199,"code":2200,"language":840},[838],"想法（Voice）\n    ↓\nAI 理解、结构化\n    ↓\n动态项目树（树形知识库）\n    ↓\n节点 → 虚拟功能（接口契约 + AI 生成的 mock 行为）\n    ↓\n沿树连接 → 虚拟系统（系统的数字孪生）\n    ↓\n数据流动仿真（端到端场景全部跑通）\n    ↓\n人工确认、契约冻结\n    ↓\nAgent 并行实化（虚拟 → 真实，逐节点替换）\n    ↓\n仿真场景 → 自动化测试 → 自动部署\n",[842,2202,2200],{"__ignoreMap":734},[10,2204,2205],{},"在这个范式里，开发者的工作重心彻底改变：",[177,2207,2208,2214],{},[180,2209,2210,2213],{},[51,2211,2212],{},"人负责","：产生想法、做决策、在仿真中审视设计、确认方向",[180,2215,2216,2219],{},[51,2217,2218],{},"AI 负责","：采集思维、维护项目树、生成虚拟功能、执行仿真、实化代码、验证结果",[10,2221,2222,2223,2226],{},"软件开发不再是「写代码」，而是",[51,2224,2225],{},"培育一个持续成长的数字项目模型","。这棵动态项目树不只是需求管理工具，它是整个项目的数字生命体——代码、文档、测试、接口，都只是它在不同阶段自动生成的表现形式。",[10,2228,2229,2230],{},"芯片行业用了三十年时间证明：",[51,2231,2232],{},"先在虚拟世界里把系统跑通，是通往物理世界最快的路。",[10,2234,2235],{},"软件行业，是时候补上这一课了。",[18,2237,2238],{},[10,2239,2240],{},[51,2241,818],{},[28,2243],{},[10,2245,2246],{},[24,2247,2248],{},"本文为 v0.2 草稿，欢迎讨论。",[2250,2251,2252],"style",{},"html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":734,"searchDepth":735,"depth":735,"links":2254},[2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274],{"id":829,"depth":735,"text":830},{"id":882,"depth":735,"text":883},{"id":923,"depth":735,"text":924},{"id":973,"depth":735,"text":974},{"id":1216,"depth":735,"text":1217},{"id":1278,"depth":735,"text":1279},{"id":1335,"depth":735,"text":1336},{"id":1408,"depth":735,"text":1409},{"id":1453,"depth":735,"text":1454},{"id":1493,"depth":735,"text":1494},{"id":1593,"depth":735,"text":1594},{"id":1642,"depth":735,"text":1643},{"id":1683,"depth":735,"text":1684},{"id":1733,"depth":735,"text":1734},{"id":1925,"depth":735,"text":1926},{"id":1985,"depth":735,"text":1986},{"id":2038,"depth":735,"text":2039},{"id":2111,"depth":735,"text":2112},{"id":2155,"depth":735,"text":2156},{"id":2195,"depth":735,"text":2196},"https:\u002F\u002Fimages.xtop.dev\u002Fblogs\u002F2026\u002F07\u002Fai-native-simulation-first.webp","2026-07-17","Why AI-era development should learn from chip design: grow a dynamic project tree from voice input, wire virtual functions into a virtual system, prove the design with data-flow simulation — and only then write real code.",{},"\u002Fblogs\u002Fai-native-simulation-first-bilingual",{"title":787,"description":2277},"blogs\u002Fai-native-simulation-first-bilingual",[2283,2284,2285,2286,2287,2288,2289,2290],"ai-native","software-engineering","simulation","methodology","ai-agents","digital-twin","knowledge-tree","workflow","w0sCrJ3tqDdGYHdQd-NhSHEFmPpFF-7XyQjNFUz720o",[2293,3353,3881],{"id":786,"title":787,"body":2294,"category":766,"cover":2275,"date":2276,"description":2277,"draft":769,"extension":770,"meta":3350,"navigation":772,"path":2279,"readingTime":774,"seo":3351,"stem":2281,"tags":3352,"__hash__":2291},{"type":7,"value":2295,"toc":3328},[2296,2314,2320,2322,2324,2326,2331,2335,2337,2349,2353,2355,2357,2361,2365,2369,2373,2375,2379,2381,2383,2387,2389,2391,2395,2399,2401,2406,2414,2416,2418,2423,2427,2431,2583,2587,2589,2591,2595,2609,2617,2621,2627,2629,2633,2637,2642,2646,2656,2660,2664,2666,2670,2672,2677,2681,2683,2705,2709,2713,2715,2717,2721,2725,2731,2737,2741,2743,2745,2750,2752,2756,2760,2764,2768,2770,2775,2777,2787,2791,2795,2797,2803,2805,2809,2811,2813,2815,2833,2839,2841,2843,2845,2850,2854,2856,2868,2872,2874,2876,2880,2884,2888,2892,2894,2898,2900,2902,2906,2908,2910,2914,2918,2920,2925,2933,2935,2937,2942,2946,2950,3102,3106,3108,3110,3114,3128,3136,3140,3146,3148,3152,3156,3161,3165,3173,3177,3181,3183,3187,3189,3194,3198,3200,3222,3226,3230,3232,3234,3238,3242,3248,3254,3258,3260,3262,3267,3269,3273,3277,3281,3285,3287,3292,3294,3304,3308,3312,3314,3320,3322,3326],[18,2297,2298,2310],{},[10,2299,2300,797,2302,801,2304,805,2306,809,2308,813],{},[51,2301,796],{},[51,2303,800],{},[51,2305,804],{},[51,2307,808],{},[51,2309,812],{},[10,2311,2312],{},[51,2313,818],{},[18,2315,2316],{},[10,2317,22,2318],{},[24,2319,26],{},[28,2321],{},[37,2323,830],{"id":829},[10,2325,833],{},[835,2327,2329],{"className":2328,"code":839,"language":840},[838],[842,2330,839],{"__ignoreMap":734},[10,2332,846,2333,850],{},[51,2334,849],{},[10,2336,853],{},[177,2338,2339,2341,2343,2345,2347],{},[180,2340,858],{},[180,2342,861],{},[180,2344,864],{},[180,2346,867],{},[180,2348,870],{},[10,2350,873,2351],{},[51,2352,876],{},[10,2354,879],{},[37,2356,883],{"id":882},[10,2358,886,2359],{},[51,2360,889],{},[10,2362,892,2363,896],{},[51,2364,895],{},[10,2366,899,2367,382],{},[51,2368,902],{},[10,2370,905,2371,909],{},[51,2372,908],{},[10,2374,912],{},[10,2376,2377],{},[51,2378,917],{},[10,2380,920],{},[37,2382,924],{"id":923},[10,2384,927,2385,382],{},[51,2386,930],{},[10,2388,933],{},[10,2390,936],{},[10,2392,2393],{},[51,2394,941],{},[18,2396,2397],{},[10,2398,946],{},[10,2400,949],{},[835,2402,2404],{"className":2403,"code":953,"language":840},[838],[842,2405,953],{"__ignoreMap":734},[10,2407,958,2408,962,2410,966,2412,970],{},[842,2409,961],{},[842,2411,965],{},[51,2413,969],{},[37,2415,974],{"id":973},[10,2417,977],{},[835,2419,2421],{"className":2420,"code":981,"language":840},[838],[842,2422,981],{"__ignoreMap":734},[10,2424,986,2425,382],{},[51,2426,989],{},[10,2428,992,2429,175],{},[51,2430,995],{},[835,2432,2433],{"className":998,"code":999,"language":1000,"meta":734,"style":734},[842,2434,2435,2443,2451,2461,2469,2485,2491,2515,2539,2545,2551,2557,2563,2573],{"__ignoreMap":734},[1004,2436,2437,2439,2441],{"class":1006,"line":1007},[1004,2438,1011],{"class":1010},[1004,2440,175],{"class":1014},[1004,2442,1018],{"class":1017},[1004,2444,2445,2447,2449],{"class":1006,"line":735},[1004,2446,1023],{"class":1010},[1004,2448,175],{"class":1014},[1004,2450,1028],{"class":1017},[1004,2452,2453,2455,2457,2459],{"class":1006,"line":741},[1004,2454,1033],{"class":1010},[1004,2456,175],{"class":1014},[1004,2458,1038],{"class":1017},[1004,2460,1042],{"class":1041},[1004,2462,2463,2465,2467],{"class":1006,"line":1045},[1004,2464,1048],{"class":1010},[1004,2466,175],{"class":1014},[1004,2468,1053],{"class":1017},[1004,2470,2471,2473,2475,2477,2479,2481,2483],{"class":1006,"line":1056},[1004,2472,1059],{"class":1010},[1004,2474,175],{"class":1014},[1004,2476,1064],{"class":1014},[1004,2478,1067],{"class":1017},[1004,2480,1070],{"class":1014},[1004,2482,1073],{"class":1017},[1004,2484,1076],{"class":1014},[1004,2486,2487,2489],{"class":1006,"line":1079},[1004,2488,1082],{"class":1010},[1004,2490,1085],{"class":1014},[1004,2492,2493,2495,2497,2499,2501,2503,2505,2507,2509,2511,2513],{"class":1006,"line":1088},[1004,2494,1091],{"class":1010},[1004,2496,175],{"class":1014},[1004,2498,1096],{"class":1014},[1004,2500,1099],{"class":1010},[1004,2502,175],{"class":1014},[1004,2504,1104],{"class":1017},[1004,2506,1070],{"class":1014},[1004,2508,1109],{"class":1010},[1004,2510,175],{"class":1014},[1004,2512,1114],{"class":1017},[1004,2514,1117],{"class":1014},[1004,2516,2517,2519,2521,2523,2525,2527,2529,2531,2533,2535,2537],{"class":1006,"line":1120},[1004,2518,1123],{"class":1010},[1004,2520,175],{"class":1014},[1004,2522,1128],{"class":1014},[1004,2524,1131],{"class":1010},[1004,2526,175],{"class":1014},[1004,2528,1104],{"class":1017},[1004,2530,1070],{"class":1014},[1004,2532,1140],{"class":1010},[1004,2534,175],{"class":1014},[1004,2536,1145],{"class":1017},[1004,2538,1117],{"class":1014},[1004,2540,2541,2543],{"class":1006,"line":1150},[1004,2542,1153],{"class":1010},[1004,2544,1085],{"class":1014},[1004,2546,2547,2549],{"class":1006,"line":1158},[1004,2548,1161],{"class":1014},[1004,2550,1164],{"class":1017},[1004,2552,2553,2555],{"class":1006,"line":1167},[1004,2554,1161],{"class":1014},[1004,2556,1172],{"class":1017},[1004,2558,2559,2561],{"class":1006,"line":1175},[1004,2560,1178],{"class":1010},[1004,2562,1085],{"class":1014},[1004,2564,2565,2567,2569,2571],{"class":1006,"line":1183},[1004,2566,1161],{"class":1014},[1004,2568,1189],{"class":1188},[1004,2570,175],{"class":1014},[1004,2572,1194],{"class":1017},[1004,2574,2575,2577,2579,2581],{"class":1006,"line":1197},[1004,2576,1161],{"class":1014},[1004,2578,1202],{"class":1188},[1004,2580,175],{"class":1014},[1004,2582,1207],{"class":1017},[10,2584,1210,2585],{},[51,2586,1213],{},[37,2588,1217],{"id":1216},[10,2590,1220],{},[10,2592,1223,2593,175],{},[51,2594,1226],{},[177,2596,2597,2601,2605],{},[180,2598,2599,1234],{},[51,2600,1233],{},[180,2602,2603,1240],{},[51,2604,1239],{},[180,2606,2607,1246],{},[51,2608,1245],{},[10,2610,1249,2611,1252,2613,1256,2615,382],{},[842,2612,961],{},[842,2614,1255],{},[842,2616,1259],{},[10,2618,2619],{},[51,2620,1264],{},[10,2622,1267,2623,1271,2625,1275],{},[51,2624,1270],{},[51,2626,1274],{},[37,2628,1279],{"id":1278},[10,2630,1282,2631],{},[51,2632,1285],{},[10,2634,1288,2635,1291],{},[842,2636,1059],{},[835,2638,2640],{"className":2639,"code":1295,"language":840},[838],[842,2641,1295],{"__ignoreMap":734},[10,2643,1300,2644,175],{},[51,2645,1303],{},[177,2647,2648,2650,2652],{},[180,2649,1308],{},[180,2651,1311],{},[180,2653,1314,2654,1318],{},[24,2655,1317],{},[10,2657,1321,2658,1325],{},[51,2659,1324],{},[10,2661,1328,2662,1332],{},[51,2663,1331],{},[37,2665,1336],{"id":1335},[10,2667,1339,2668,382],{},[51,2669,1342],{},[10,2671,1345],{},[835,2673,2675],{"className":2674,"code":1349,"language":840},[838],[842,2676,1349],{"__ignoreMap":734},[10,2678,1354,2679,1358],{},[51,2680,1357],{},[10,2682,1361],{},[177,2684,2685,2689,2693,2697,2701],{},[180,2686,2687,1369],{},[51,2688,1368],{},[180,2690,2691,1375],{},[51,2692,1374],{},[180,2694,2695,1381],{},[51,2696,1380],{},[180,2698,2699,1387],{},[51,2700,1386],{},[180,2702,2703,1393],{},[51,2704,1392],{},[10,2706,1396,2707,1400],{},[51,2708,1399],{},[10,2710,2711],{},[51,2712,1405],{},[37,2714,1409],{"id":1408},[10,2716,1412],{},[10,2718,2719,1418],{},[51,2720,1417],{},[10,2722,2723,1424],{},[51,2724,1423],{},[10,2726,2727,1430,2729,1434],{},[51,2728,1429],{},[51,2730,1433],{},[10,2732,2733,1440,2735,1444],{},[51,2734,1439],{},[842,2736,1443],{},[10,2738,2739,1450],{},[51,2740,1449],{},[37,2742,1454],{"id":1453},[10,2744,1457],{},[835,2746,2748],{"className":2747,"code":1461,"language":840},[838],[842,2749,1461],{"__ignoreMap":734},[10,2751,1466],{},[10,2753,2754,1472],{},[51,2755,1471],{},[10,2757,2758,1478],{},[51,2759,1477],{},[10,2761,2762,1484],{},[51,2763,1483],{},[10,2765,2766,1490],{},[51,2767,1489],{},[37,2769,1494],{"id":1493},[835,2771,2773],{"className":2772,"code":1498,"language":840},[838],[842,2774,1498],{"__ignoreMap":734},[10,2776,1503],{},[177,2778,2779,2783],{},[180,2780,2781,1511],{},[51,2782,1510],{},[180,2784,2785,1517],{},[51,2786,1516],{},[10,2788,1520,2789,1524],{},[51,2790,1523],{},[10,2792,1527,2793],{},[51,2794,1530],{},[10,2796,1533],{},[18,2798,2799],{},[10,2800,2801],{},[51,2802,818],{},[28,2804],{},[10,2806,2807],{},[24,2808,1546],{},[28,2810],{},[28,2812],{},[388,2814,1554],{"id":1553},[18,2816,2817,2829],{},[10,2818,2819,1562,2821,1570,2825,1574,2827,1578],{},[51,2820,1561],{},[51,2822,1565,2823,1569],{},[51,2824,1568],{},[51,2826,1573],{},[51,2828,1577],{},[10,2830,2831],{},[51,2832,818],{},[18,2834,2835],{},[10,2836,22,2837],{},[24,2838,398],{},[28,2840],{},[37,2842,1594],{"id":1593},[10,2844,1597],{},[835,2846,2848],{"className":2847,"code":1601,"language":840},[838],[842,2849,1601],{"__ignoreMap":734},[10,2851,1606,2852,1610],{},[51,2853,1609],{},[10,2855,1613],{},[177,2857,2858,2860,2862,2864,2866],{},[180,2859,1618],{},[180,2861,1621],{},[180,2863,1624],{},[180,2865,1627],{},[180,2867,1630],{},[10,2869,1633,2870],{},[51,2871,1636],{},[10,2873,1639],{},[37,2875,1643],{"id":1642},[10,2877,1646,2878],{},[51,2879,1649],{},[10,2881,1652,2882,1656],{},[51,2883,1655],{},[10,2885,1659,2886,732],{},[51,2887,1662],{},[10,2889,1665,2890,1669],{},[51,2891,1668],{},[10,2893,1672],{},[10,2895,2896],{},[51,2897,1677],{},[10,2899,1680],{},[37,2901,1684],{"id":1683},[10,2903,1687,2904,732],{},[51,2905,1690],{},[10,2907,1693],{},[10,2909,1696],{},[10,2911,2912],{},[51,2913,1701],{},[18,2915,2916],{},[10,2917,1706],{},[10,2919,1709],{},[835,2921,2923],{"className":2922,"code":1713,"language":840},[838],[842,2924,1713],{"__ignoreMap":734},[10,2926,1718,2927,1722,2929,1726,2931,1730],{},[842,2928,1721],{},[842,2930,1725],{},[51,2932,1729],{},[37,2934,1734],{"id":1733},[10,2936,1737],{},[835,2938,2940],{"className":2939,"code":1741,"language":840},[838],[842,2941,1741],{"__ignoreMap":734},[10,2943,1746,2944,732],{},[51,2945,1749],{},[10,2947,1752,2948,534],{},[51,2949,1755],{},[835,2951,2952],{"className":998,"code":1758,"language":1000,"meta":734,"style":734},[842,2953,2954,2962,2970,2980,2988,3004,3010,3034,3058,3064,3070,3076,3082,3092],{"__ignoreMap":734},[1004,2955,2956,2958,2960],{"class":1006,"line":1007},[1004,2957,1011],{"class":1010},[1004,2959,175],{"class":1014},[1004,2961,1769],{"class":1017},[1004,2963,2964,2966,2968],{"class":1006,"line":735},[1004,2965,1023],{"class":1010},[1004,2967,175],{"class":1014},[1004,2969,1778],{"class":1017},[1004,2971,2972,2974,2976,2978],{"class":1006,"line":741},[1004,2973,1033],{"class":1010},[1004,2975,175],{"class":1014},[1004,2977,1038],{"class":1017},[1004,2979,1042],{"class":1041},[1004,2981,2982,2984,2986],{"class":1006,"line":1045},[1004,2983,1048],{"class":1010},[1004,2985,175],{"class":1014},[1004,2987,1053],{"class":1017},[1004,2989,2990,2992,2994,2996,2998,3000,3002],{"class":1006,"line":1056},[1004,2991,1059],{"class":1010},[1004,2993,175],{"class":1014},[1004,2995,1064],{"class":1014},[1004,2997,1807],{"class":1017},[1004,2999,1070],{"class":1014},[1004,3001,1812],{"class":1017},[1004,3003,1076],{"class":1014},[1004,3005,3006,3008],{"class":1006,"line":1079},[1004,3007,1082],{"class":1010},[1004,3009,1085],{"class":1014},[1004,3011,3012,3014,3016,3018,3020,3022,3024,3026,3028,3030,3032],{"class":1006,"line":1088},[1004,3013,1091],{"class":1010},[1004,3015,175],{"class":1014},[1004,3017,1096],{"class":1014},[1004,3019,1099],{"class":1010},[1004,3021,175],{"class":1014},[1004,3023,1104],{"class":1017},[1004,3025,1070],{"class":1014},[1004,3027,1109],{"class":1010},[1004,3029,175],{"class":1014},[1004,3031,1114],{"class":1017},[1004,3033,1117],{"class":1014},[1004,3035,3036,3038,3040,3042,3044,3046,3048,3050,3052,3054,3056],{"class":1006,"line":1120},[1004,3037,1123],{"class":1010},[1004,3039,175],{"class":1014},[1004,3041,1128],{"class":1014},[1004,3043,1131],{"class":1010},[1004,3045,175],{"class":1014},[1004,3047,1104],{"class":1017},[1004,3049,1070],{"class":1014},[1004,3051,1140],{"class":1010},[1004,3053,175],{"class":1014},[1004,3055,1145],{"class":1017},[1004,3057,1117],{"class":1014},[1004,3059,3060,3062],{"class":1006,"line":1150},[1004,3061,1153],{"class":1010},[1004,3063,1085],{"class":1014},[1004,3065,3066,3068],{"class":1006,"line":1158},[1004,3067,1161],{"class":1014},[1004,3069,1881],{"class":1017},[1004,3071,3072,3074],{"class":1006,"line":1167},[1004,3073,1161],{"class":1014},[1004,3075,1888],{"class":1017},[1004,3077,3078,3080],{"class":1006,"line":1175},[1004,3079,1178],{"class":1010},[1004,3081,1085],{"class":1014},[1004,3083,3084,3086,3088,3090],{"class":1006,"line":1183},[1004,3085,1161],{"class":1014},[1004,3087,1189],{"class":1188},[1004,3089,175],{"class":1014},[1004,3091,1905],{"class":1017},[1004,3093,3094,3096,3098,3100],{"class":1006,"line":1197},[1004,3095,1161],{"class":1014},[1004,3097,1202],{"class":1188},[1004,3099,175],{"class":1014},[1004,3101,1916],{"class":1017},[10,3103,1919,3104],{},[51,3105,1922],{},[37,3107,1926],{"id":1925},[10,3109,1929],{},[10,3111,1932,3112,534],{},[51,3113,1935],{},[177,3115,3116,3120,3124],{},[180,3117,3118,1943],{},[51,3119,1942],{},[180,3121,3122,1949],{},[51,3123,1948],{},[180,3125,3126,1955],{},[51,3127,1954],{},[10,3129,1958,3130,1961,3132,1964,3134,732],{},[842,3131,1725],{},[842,3133,1255],{},[842,3135,1259],{},[10,3137,3138],{},[51,3139,1971],{},[10,3141,1974,3142,1978,3144,1982],{},[51,3143,1977],{},[51,3145,1981],{},[37,3147,1986],{"id":1985},[10,3149,1989,3150],{},[51,3151,1992],{},[10,3153,1995,3154,1998],{},[842,3155,1059],{},[835,3157,3159],{"className":3158,"code":2002,"language":840},[838],[842,3160,2002],{"__ignoreMap":734},[10,3162,2007,3163,534],{},[51,3164,2010],{},[177,3166,3167,3169,3171],{},[180,3168,2015],{},[180,3170,2018],{},[180,3172,2021],{},[10,3174,2024,3175,2028],{},[51,3176,2027],{},[10,3178,2031,3179,2035],{},[51,3180,2034],{},[37,3182,2039],{"id":2038},[10,3184,2042,3185,732],{},[51,3186,2045],{},[10,3188,2048],{},[835,3190,3192],{"className":3191,"code":2052,"language":840},[838],[842,3193,2052],{"__ignoreMap":734},[10,3195,2057,3196,2061],{},[51,3197,2060],{},[10,3199,2064],{},[177,3201,3202,3206,3210,3214,3218],{},[180,3203,3204,2072],{},[51,3205,2071],{},[180,3207,3208,2078],{},[51,3209,2077],{},[180,3211,3212,2084],{},[51,3213,2083],{},[180,3215,3216,2090],{},[51,3217,2089],{},[180,3219,3220,2096],{},[51,3221,2095],{},[10,3223,2099,3224,2103],{},[51,3225,2102],{},[10,3227,3228],{},[51,3229,2108],{},[37,3231,2112],{"id":2111},[10,3233,2115],{},[10,3235,3236,2121],{},[51,3237,2120],{},[10,3239,3240,2127],{},[51,3241,2126],{},[10,3243,3244,2133,3246,2137],{},[51,3245,2132],{},[51,3247,2136],{},[10,3249,3250,2143,3252,2146],{},[51,3251,2142],{},[842,3253,1443],{},[10,3255,3256,2152],{},[51,3257,2151],{},[37,3259,2156],{"id":2155},[10,3261,2159],{},[835,3263,3265],{"className":3264,"code":2163,"language":840},[838],[842,3266,2163],{"__ignoreMap":734},[10,3268,2168],{},[10,3270,3271,2174],{},[51,3272,2173],{},[10,3274,3275,2180],{},[51,3276,2179],{},[10,3278,3279,2186],{},[51,3280,2185],{},[10,3282,3283,2192],{},[51,3284,2191],{},[37,3286,2196],{"id":2195},[835,3288,3290],{"className":3289,"code":2200,"language":840},[838],[842,3291,2200],{"__ignoreMap":734},[10,3293,2205],{},[177,3295,3296,3300],{},[180,3297,3298,2213],{},[51,3299,2212],{},[180,3301,3302,2219],{},[51,3303,2218],{},[10,3305,2222,3306,2226],{},[51,3307,2225],{},[10,3309,2229,3310],{},[51,3311,2232],{},[10,3313,2235],{},[18,3315,3316],{},[10,3317,3318],{},[51,3319,818],{},[28,3321],{},[10,3323,3324],{},[24,3325,2248],{},[2250,3327,2252],{},{"title":734,"searchDepth":735,"depth":735,"links":3329},[3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349],{"id":829,"depth":735,"text":830},{"id":882,"depth":735,"text":883},{"id":923,"depth":735,"text":924},{"id":973,"depth":735,"text":974},{"id":1216,"depth":735,"text":1217},{"id":1278,"depth":735,"text":1279},{"id":1335,"depth":735,"text":1336},{"id":1408,"depth":735,"text":1409},{"id":1453,"depth":735,"text":1454},{"id":1493,"depth":735,"text":1494},{"id":1593,"depth":735,"text":1594},{"id":1642,"depth":735,"text":1643},{"id":1683,"depth":735,"text":1684},{"id":1733,"depth":735,"text":1734},{"id":1925,"depth":735,"text":1926},{"id":1985,"depth":735,"text":1986},{"id":2038,"depth":735,"text":2039},{"id":2111,"depth":735,"text":2112},{"id":2155,"depth":735,"text":2156},{"id":2195,"depth":735,"text":2196},{},{"title":787,"description":2277},[2283,2284,2285,2286,2287,2288,2289,2290],{"id":3354,"title":3355,"body":3356,"category":766,"cover":3868,"date":3869,"description":3870,"draft":769,"extension":770,"meta":3871,"navigation":772,"path":3872,"readingTime":774,"seo":3873,"stem":3874,"tags":3875,"__hash__":3880},"blogs\u002Fblogs\u002Fbuilding-xtop-dev.md","Building xtop.dev in Three Days: What AI Got Right and Wrong",{"type":7,"value":3357,"toc":3845},[3358,3361,3364,3367,3371,3374,3377,3388,3394,3398,3401,3437,3440,3446,3452,3462,3466,3472,3481,3487,3490,3494,3497,3501,3504,3511,3514,3521,3532,3547,3551,3558,3561,3565,3568,3572,3575,3582,3585,3590,3594,3597,3614,3617,3624,3628,3631,3634,3638,3641,3645,3648,3651,3654,3658,3661,3667,3671,3737,3740,3744,3747,3759,3765,3771,3785,3788,3792,3795,3827,3832,3835,3837],[10,3359,3360],{},"Three days ago, this site was a Dynadot parking page. Today it's a full personal site — six pages, a content system, a working contact form backed by a real .NET API, deployed across Cloudflare Pages and a $5 VPS.",[10,3362,3363],{},"I built most of it pairing with Claude.",[10,3365,3366],{},"This isn't another \"AI wrote my code!\" post. It's more honest than that — a build log of what AI actually helped with, what it got wrong, and the decisions I still had to make myself.",[37,3368,3370],{"id":3369},"why-bother-with-a-personal-site","Why bother with a personal site",[10,3372,3373],{},"I've been freelancing on and off for a few years. Most of my leads came through referrals and a pinned GitHub repo. That worked, but it put a ceiling on who could find me.",[10,3375,3376],{},"A personal site does three things a GitHub profile can't:",[333,3378,3379,3382,3385],{},[180,3380,3381],{},"It tells a story, not just a resume",[180,3383,3384],{},"It ranks for long-tail searches (\"nuxt dotnet freelance developer\")",[180,3386,3387],{},"It's where cold leads can actually reach you",[10,3389,3390,3391,382],{},"The goal wasn't perfection. It was ",[51,3392,3393],{},"something real, shipped, that represents me",[37,3395,3397],{"id":3396},"the-stack-and-why","The stack, and why",[10,3399,3400],{},"I picked the stack before talking to the AI. This matters. If you let the AI pick, you get whatever is trendy in its training data.",[177,3402,3403,3409,3419,3425,3431],{},[180,3404,3405,3408],{},[51,3406,3407],{},"Frontend",": Nuxt 4 + Nuxt UI 4 + Tailwind v4 + TypeScript",[180,3410,3411,3414,3415,3418],{},[51,3412,3413],{},"Content",": ",[842,3416,3417],{},"@nuxt\u002Fcontent"," v3 (Markdown-driven blog, projects, travel)",[180,3420,3421,3424],{},[51,3422,3423],{},"Backend",": .NET 8 Minimal API (just for the contact form)",[180,3426,3427,3430],{},[51,3428,3429],{},"Hosting",": Cloudflare Pages (frontend) + $5 VPS (backend)",[180,3432,3433,3436],{},[51,3434,3435],{},"Images",": Cloudflare R2 with a custom domain",[10,3438,3439],{},"Three constraints drove these choices:",[10,3441,3442,3445],{},[51,3443,3444],{},"It should stay cheap."," Total cost is around $5\u002Fmonth. Cloudflare Pages and R2 are effectively free at my scale.",[10,3447,3448,3451],{},[51,3449,3450],{},"It should show what I can actually do."," Having a real .NET backend on a real VPS — even just for a contact form — is a live demo of my full-stack work. A static-only site can't claim that.",[10,3453,3454,3457,3458,3461],{},[51,3455,3456],{},"It should be fun to maintain."," All content lives in Markdown files inside ",[842,3459,3460],{},"content\u002F",". Writing a blog post is just opening VSCode and typing. No CMS. No database. No admin panel.",[37,3463,3465],{"id":3464},"three-days-roughly","Three days, roughly",[10,3467,3468,3471],{},[51,3469,3470],{},"Day 1 — Scaffolding and structure."," Six pages wired up with placeholder content. Design tokens locked in: Playfair Display serif, teal palette, lots of whitespace. The shape of the site was visible by evening.",[10,3473,3474,3477,3478,3480],{},[51,3475,3476],{},"Day 2 — Content system and backend."," Migrated mock data into ",[842,3479,3417],{}," across three collections (blogs, projects, travel). Built the .NET 8 contact API with SMTP email delivery and rate limiting. Wired the form to the backend.",[10,3482,3483,3486],{},[51,3484,3485],{},"Day 3 — Polish and ship."," Error page, SEO meta tags, mobile breakpoints, image pipeline to R2, DNS, SSL, deployment. All the finish-tax work that turns a prototype into a live site.",[10,3488,3489],{},"No weekend work magic. Just focused days with a collaborator that never slept.",[37,3491,3493],{"id":3492},"where-ai-actually-helped","Where AI actually helped",[10,3495,3496],{},"Let me be specific, because \"AI helped me build this\" usually means nothing.",[63,3498,3500],{"id":3499},"scaffolding-that-would-have-taken-a-full-day-took-two-hours","Scaffolding that would have taken a full day took two hours",[10,3502,3503],{},"I described the six pages I wanted with rough layouts. Claude generated the initial Vue files with proper structure, placeholder content, and consistent styling tokens. I reviewed, caught inconsistencies, and iterated.",[10,3505,3506,3507,3510],{},"This is the sweet spot for AI right now — ",[51,3508,3509],{},"bulk generation of familiar patterns",". It knows what a blog list page looks like. It knows how Nuxt pages are structured. It can write fifteen similar-but-not-identical components in ten minutes.",[10,3512,3513],{},"Doing this by hand would have been a full day of copy-paste-modify. I'd have been bored. I'd have introduced bugs.",[63,3515,3517,3518,3520],{"id":3516},"migration-from-mock-data-to-nuxtcontent-was-painless","Migration from mock data to ",[842,3519,3417],{}," was painless",[10,3522,3523,3524,3527,3528,3531],{},"I started Day 1 with hardcoded arrays of blog posts in a composable. Day 2 morning, I wanted Markdown files instead. I described the migration in two sentences. Claude rewrote the pages to use ",[842,3525,3526],{},"queryCollection()",", added the right schema to ",[842,3529,3530],{},"content.config.ts",", and walked me through the directory structure.",[10,3533,3534,3535,3538,3539,3542,3543,3546],{},"The migration across three collections took about thirty minutes. The nested travel structure (",[842,3536,3537],{},"content\u002Ftravel\u002Fjapan\u002Fxxx.md",") needed a judgment call — I wanted ",[842,3540,3541],{},"\u002Ftravel\u002F[slug]"," routing instead of ",[842,3544,3545],{},"\u002Ftravel\u002F[country]\u002F[slug]",", which forced a different query pattern. I made that call. Claude implemented it.",[63,3548,3550],{"id":3549},"debugging-the-weird-stuff","Debugging the weird stuff",[10,3552,3553,3554,3557],{},"On Day 3 I hit a Vue 3 hydration mismatch warning that seemed unrelated to anything I'd just changed. I pasted the stack trace. Claude diagnosed it as an SSR issue with my scroll-reveal composable — CSS was applying ",[842,3555,3556],{},"opacity: 0"," during hydration, before the IntersectionObserver could kick in, creating a mismatch between the server HTML and the hydrated state.",[10,3559,3560],{},"The fix was subtle: move the \"hidden state\" from CSS to a JS-applied class, so the server HTML matched what the client first renders. I wouldn't have figured that out alone in under an hour. Claude found it in one exchange.",[37,3562,3564],{"id":3563},"where-ai-didnt-help","Where AI didn't help",[10,3566,3567],{},"Equally specific, because this matters more.",[63,3569,3571],{"id":3570},"taste","Taste",[10,3573,3574],{},"Claude can generate a hero section. It cannot tell me whether a serif font for headings is right for this site.",[10,3576,3577,3578,3581],{},"That decision — Playfair Display serif, teal palette, lots of whitespace — was mine. The AI can execute a design. It cannot make the design ",[24,3579,3580],{},"feel"," like me.",[10,3583,3584],{},"Every choice that touched identity was mine: the color palette, the typography, the copywriting voice, the \"Lost at sea\" tone on the 404 page. When I let Claude write copy, it came back as generic marketing-speak. When I wrote the copy and asked Claude to polish tone, it was better.",[10,3586,3587],{},[51,3588,3589],{},"AI is a great executor, a poor art director.",[63,3591,3593],{"id":3592},"deciding-what-not-to-build","Deciding what not to build",[10,3595,3596],{},"In three days, the discipline to cut matters more than the speed to build. I considered adding:",[177,3598,3599,3602,3605,3608,3611],{},[180,3600,3601],{},"A newsletter signup",[180,3603,3604],{},"Comments on blog posts",[180,3606,3607],{},"An analytics dashboard",[180,3609,3610],{},"A WebGL-animated hero section",[180,3612,3613],{},"i18n for English + Chinese",[10,3615,3616],{},"I built none of them. Not one.",[10,3618,3619,3620,3623],{},"Each would have added a day of work and zero client acquisition. Claude would have happily helped me build all five. The discipline to ",[51,3621,3622],{},"cut"," features is a human skill. AI defaults to \"yes, let's build that\" because it has no stake in my time.",[63,3625,3627],{"id":3626},"product-positioning","Product positioning",[10,3629,3630],{},"The hardest part of the site isn't the code. It's the Services page — deciding what I offer, what I don't, what pricing tier I show, what process I describe.",[10,3632,3633],{},"I spent more time on that one page than on any other. Claude helped me draft and iterate, but the actual choices — \"I don't do WordPress sites\", \"I'm fine with three-week projects but not three-month ones\", \"my minimum is $1,000\" — those were me reading my own calendar and bank account.",[37,3635,3637],{"id":3636},"the-parts-nobody-talks-about","The parts nobody talks about",[10,3639,3640],{},"Two surprises worth flagging if you're about to do something similar:",[63,3642,3644],{"id":3643},"the-finish-tax","The \"finish\" tax",[10,3646,3647],{},"Day 3 took longer than Day 1 and Day 2 combined. Error pages, SEO meta tags, mobile breakpoints, the contact form rate limiter, the hydration bug, the R2 image upload pipeline, the deployment guide, the DNS configuration, the SSL renewal cron.",[10,3649,3650],{},"None of this is glamorous. All of it is required.",[10,3652,3653],{},"If you've built a side project and felt like you were \"almost done\" for the last stretch — yeah, you were. The finish tax is real, and it doesn't care how fast the scaffolding went.",[63,3655,3657],{"id":3656},"the-deployment-rabbit-hole","The deployment rabbit hole",[10,3659,3660],{},"I initially tried Cloudflare Workers because it sounded fancier. Spent a morning on it before I realized it was the wrong tool — I didn't need edge compute, I needed static hosting. Switched to Cloudflare Pages and was deployed in ten minutes.",[10,3662,3663,3666],{},[51,3664,3665],{},"Sometimes the answer is \"use the simpler thing.\""," AI tends to suggest more powerful tools than you need. Push back.",[37,3668,3670],{"id":3669},"what-it-cost","What it cost",[68,3672,3673,3683],{},[71,3674,3675],{},[74,3676,3677,3680],{},[77,3678,3679],{},"Item",[77,3681,3682],{},"Monthly",[86,3684,3685,3693,3701,3709,3717,3725],{},[74,3686,3687,3690],{},[91,3688,3689],{},"Domain (xtop.dev)",[91,3691,3692],{},"~$0.60 (amortized)",[74,3694,3695,3698],{},[91,3696,3697],{},"VPS ($5\u002Fmonth, for .NET API)",[91,3699,3700],{},"$5.00",[74,3702,3703,3706],{},[91,3704,3705],{},"Cloudflare Pages",[91,3707,3708],{},"$0 (free tier, unlimited bandwidth)",[74,3710,3711,3714],{},[91,3712,3713],{},"Cloudflare R2 (image storage)",[91,3715,3716],{},"$0 (under 10GB)",[74,3718,3719,3722],{},[91,3720,3721],{},"SMTP (QQ Mail for contact form)",[91,3723,3724],{},"$0",[74,3726,3727,3732],{},[91,3728,3729],{},[51,3730,3731],{},"Total",[91,3733,3734],{},[51,3735,3736],{},"~$5.60\u002Fmonth",[10,3738,3739],{},"First client inquiry pays for 10+ years of hosting.",[37,3741,3743],{"id":3742},"would-i-do-it-again-this-way","Would I do it again this way?",[10,3745,3746],{},"Mostly, yes.",[10,3748,3749,3752,3753,3755,3756,382],{},[51,3750,3751],{},"Kept",": Nuxt + ",[842,3754,3417],{}," + Cloudflare Pages. Markdown-driven sites are a joy to maintain. Every new post is one file, one ",[842,3757,3758],{},"git push",[10,3760,3761,3764],{},[51,3762,3763],{},"Kept with caveats",": The .NET backend. Overkill for just a contact form, but it's a live portfolio piece — \"this developer can actually deploy a Linux VPS with Nginx and systemd\" — that a Vercel serverless function can't replicate.",[10,3766,3767,3770],{},[51,3768,3769],{},"Would change",": I'd pick the typography and color palette in the first hour instead of drifting into it. Deciding design late caused rework. On a three-day timeline, two hours of rework is a lot.",[10,3772,3773,3776,3777,3780,3781,3784],{},[51,3774,3775],{},"Surprised me",": How much AI helped with the ",[24,3778,3779],{},"boring"," parts (scaffolding, refactors, deployment scripts) versus the ",[24,3782,3783],{},"interesting"," parts (design, positioning, voice). The boring parts are where AI shines. The interesting parts stay human.",[10,3786,3787],{},"Three days is possible because AI compresses the boring parts. It doesn't compress the interesting ones.",[37,3789,3791],{"id":3790},"if-youre-thinking-of-doing-this","If you're thinking of doing this",[10,3793,3794],{},"My suggestions, in order of importance:",[333,3796,3797,3803,3809,3815,3821],{},[180,3798,3799,3802],{},[51,3800,3801],{},"Pick your stack before you open the AI chat."," Otherwise you'll build a trendy stack instead of one you'll enjoy maintaining.",[180,3804,3805,3808],{},[51,3806,3807],{},"Ship one version end-to-end before you polish."," My first version was ugly. Shipping it unlocked every subsequent decision.",[180,3810,3811,3814],{},[51,3812,3813],{},"Write your own copy."," Let AI edit it.",[180,3816,3817,3820],{},[51,3818,3819],{},"Cut features ruthlessly."," A focused site out-performs a bloated one.",[180,3822,3823,3826],{},[51,3824,3825],{},"Get to the contact form fast."," Everything upstream of the contact form is scaffolding for the contact form.",[10,3828,3829,3830,382],{},"The site took three days. It works. People can reach me. I can write new posts in Markdown and ",[842,3831,3758],{},[10,3833,3834],{},"That's the whole pitch.",[28,3836],{},[10,3838,3839],{},[24,3840,3841,3842,382],{},"Thanks for reading. If this resonated and you need a developer who pairs well with AI but still makes the hard calls himself, ",[378,3843,3844],{"href":380},"my inbox is open",{"title":734,"searchDepth":735,"depth":735,"links":3846},[3847,3848,3849,3850,3856,3861,3865,3866,3867],{"id":3369,"depth":735,"text":3370},{"id":3396,"depth":735,"text":3397},{"id":3464,"depth":735,"text":3465},{"id":3492,"depth":735,"text":3493,"children":3851},[3852,3853,3855],{"id":3499,"depth":741,"text":3500},{"id":3516,"depth":741,"text":3854},"Migration from mock data to @nuxt\u002Fcontent was painless",{"id":3549,"depth":741,"text":3550},{"id":3563,"depth":735,"text":3564,"children":3857},[3858,3859,3860],{"id":3570,"depth":741,"text":3571},{"id":3592,"depth":741,"text":3593},{"id":3626,"depth":741,"text":3627},{"id":3636,"depth":735,"text":3637,"children":3862},[3863,3864],{"id":3643,"depth":741,"text":3644},{"id":3656,"depth":741,"text":3657},{"id":3669,"depth":735,"text":3670},{"id":3742,"depth":735,"text":3743},{"id":3790,"depth":735,"text":3791},"https:\u002F\u002Fimages.xtop.dev\u002Fblogs\u002F2026\u002F04\u002Fbuilding-xtop-dev.jpg","2026-04-20","A build log of shipping my personal developer site in 72 hours with Nuxt 4, .NET 8, and an AI collaborator. What worked, what didn't, and what I'd do differently.",{},"\u002Fblogs\u002Fbuilding-xtop-dev",{"title":3355,"description":3870},"blogs\u002Fbuilding-xtop-dev",[3876,3877,779,3878,3879],"nuxt","dotnet","indie-dev","build-log","KO_zwwpqIxYIBaRJQFb0s1UShrLYr6m8C73Oq0-9yv4",{"id":3882,"title":3883,"body":3884,"category":766,"cover":4361,"date":4362,"description":4363,"draft":769,"extension":770,"meta":4364,"navigation":772,"path":4365,"readingTime":1175,"seo":4366,"stem":4367,"tags":4368,"__hash__":4372},"blogs\u002Fblogs\u002Fnuxt-dotnet-jwt-auth.md","Nuxt 3 与 .NET 8 的 JWT 认证实践",{"type":7,"value":3885,"toc":4354},[3886,3890,3893,3896,3916,3920,3923,4006,4010,4021,4317,4321,4327,4330,4345,4348,4351],[37,3887,3889],{"id":3888},"为什么选-jwt","为什么选 JWT",[10,3891,3892],{},"在前后端分离的项目里，JWT 是最常见的认证方案之一。它把用户身份编码到一个自包含的 token 里，服务器无需维护 session 状态，天然适合分布式部署。",[10,3894,3895],{},"但 JWT 不是银弹。它有三个必须正视的问题：",[333,3897,3898,3904,3910],{},[180,3899,3900,3903],{},[51,3901,3902],{},"token 一旦签发无法吊销","，除非维护 blacklist",[180,3905,3906,3909],{},[51,3907,3908],{},"payload 可被解码","（base64 不是加密），不能放敏感信息",[180,3911,3912,3915],{},[51,3913,3914],{},"过期时间权衡","：短则频繁登录，长则安全风险",[37,3917,3919],{"id":3918},"后端net-8-配置","后端：.NET 8 配置",[10,3921,3922],{},"在 Program.cs 里加入 JWT 认证：",[835,3924,3928],{"className":3925,"code":3926,"language":3927,"meta":734,"style":734},"language-csharp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)\n    .AddJwtBearer(options =>\n    {\n        options.TokenValidationParameters = new TokenValidationParameters\n        {\n            ValidateIssuer = true,\n            ValidateAudience = true,\n            ValidateLifetime = true,\n            ValidateIssuerSigningKey = true,\n            ValidIssuer = builder.Configuration[\"Jwt:Issuer\"],\n            ValidAudience = builder.Configuration[\"Jwt:Audience\"],\n            IssuerSigningKey = new SymmetricSecurityKey(\n                Encoding.UTF8.GetBytes(builder.Configuration[\"Jwt:Key\"]))\n        };\n    });\n","csharp",[842,3929,3930,3935,3940,3945,3950,3955,3960,3965,3970,3975,3980,3985,3990,3995,4000],{"__ignoreMap":734},[1004,3931,3932],{"class":1006,"line":1007},[1004,3933,3934],{},"builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)\n",[1004,3936,3937],{"class":1006,"line":735},[1004,3938,3939],{},"    .AddJwtBearer(options =>\n",[1004,3941,3942],{"class":1006,"line":741},[1004,3943,3944],{},"    {\n",[1004,3946,3947],{"class":1006,"line":1045},[1004,3948,3949],{},"        options.TokenValidationParameters = new TokenValidationParameters\n",[1004,3951,3952],{"class":1006,"line":1056},[1004,3953,3954],{},"        {\n",[1004,3956,3957],{"class":1006,"line":1079},[1004,3958,3959],{},"            ValidateIssuer = true,\n",[1004,3961,3962],{"class":1006,"line":1088},[1004,3963,3964],{},"            ValidateAudience = true,\n",[1004,3966,3967],{"class":1006,"line":1120},[1004,3968,3969],{},"            ValidateLifetime = true,\n",[1004,3971,3972],{"class":1006,"line":1150},[1004,3973,3974],{},"            ValidateIssuerSigningKey = true,\n",[1004,3976,3977],{"class":1006,"line":1158},[1004,3978,3979],{},"            ValidIssuer = builder.Configuration[\"Jwt:Issuer\"],\n",[1004,3981,3982],{"class":1006,"line":1167},[1004,3983,3984],{},"            ValidAudience = builder.Configuration[\"Jwt:Audience\"],\n",[1004,3986,3987],{"class":1006,"line":1175},[1004,3988,3989],{},"            IssuerSigningKey = new SymmetricSecurityKey(\n",[1004,3991,3992],{"class":1006,"line":1183},[1004,3993,3994],{},"                Encoding.UTF8.GetBytes(builder.Configuration[\"Jwt:Key\"]))\n",[1004,3996,3997],{"class":1006,"line":1197},[1004,3998,3999],{},"        };\n",[1004,4001,4003],{"class":1006,"line":4002},15,[1004,4004,4005],{},"    });\n",[37,4007,4009],{"id":4008},"前端nuxt-3-拦截器","前端：Nuxt 3 拦截器",[10,4011,4012,4013,4016,4017,4020],{},"在 Nuxt 里用 ",[842,4014,4015],{},"useFetch"," 的 ",[842,4018,4019],{},"onRequest"," 钩子统一注入 token：",[835,4022,4026],{"className":4023,"code":4024,"language":4025,"meta":734,"style":734},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export const useApi = () => {\n  const token = useCookie('auth-token')\n\n  return $fetch.create({\n    baseURL: useRuntimeConfig().public.apiBase,\n    onRequest({ options }) {\n      if (token.value) {\n        options.headers = {\n          ...options.headers,\n          Authorization: `Bearer ${token.value}`\n        }\n      }\n    },\n    onResponseError({ response }) {\n      if (response.status === 401) {\n        navigateTo('\u002Flogin')\n      }\n    }\n  })\n}\n","typescript",[842,4027,4028,4053,4082,4087,4105,4131,4148,4169,4183,4197,4222,4227,4232,4237,4251,4275,4292,4297,4303,4311],{"__ignoreMap":734},[1004,4029,4030,4034,4038,4041,4044,4047,4050],{"class":1006,"line":1007},[1004,4031,4033],{"class":4032},"s7zQu","export",[1004,4035,4037],{"class":4036},"spNyl"," const",[1004,4039,4040],{"class":1188}," useApi ",[1004,4042,4043],{"class":1014},"=",[1004,4045,4046],{"class":1014}," ()",[1004,4048,4049],{"class":4036}," =>",[1004,4051,4052],{"class":1014}," {\n",[1004,4054,4055,4058,4061,4064,4068,4071,4074,4077,4079],{"class":1006,"line":735},[1004,4056,4057],{"class":4036},"  const",[1004,4059,4060],{"class":1188}," token",[1004,4062,4063],{"class":1014}," =",[1004,4065,4067],{"class":4066},"s2Zo4"," useCookie",[1004,4069,4070],{"class":1010},"(",[1004,4072,4073],{"class":1014},"'",[1004,4075,4076],{"class":1017},"auth-token",[1004,4078,4073],{"class":1014},[1004,4080,4081],{"class":1010},")\n",[1004,4083,4084],{"class":1006,"line":741},[1004,4085,4086],{"emptyLinePlaceholder":772},"\n",[1004,4088,4089,4092,4095,4097,4100,4102],{"class":1006,"line":1045},[1004,4090,4091],{"class":4032},"  return",[1004,4093,4094],{"class":1188}," $fetch",[1004,4096,382],{"class":1014},[1004,4098,4099],{"class":4066},"create",[1004,4101,4070],{"class":1010},[1004,4103,4104],{"class":1014},"{\n",[1004,4106,4107,4110,4112,4115,4118,4120,4123,4125,4128],{"class":1006,"line":1056},[1004,4108,4109],{"class":1010},"    baseURL",[1004,4111,175],{"class":1014},[1004,4113,4114],{"class":4066}," useRuntimeConfig",[1004,4116,4117],{"class":1010},"()",[1004,4119,382],{"class":1014},[1004,4121,4122],{"class":1188},"public",[1004,4124,382],{"class":1014},[1004,4126,4127],{"class":1188},"apiBase",[1004,4129,4130],{"class":1014},",\n",[1004,4132,4133,4136,4139,4143,4146],{"class":1006,"line":1079},[1004,4134,4135],{"class":1010},"    onRequest",[1004,4137,4138],{"class":1014},"({",[1004,4140,4142],{"class":4141},"sHdIc"," options",[1004,4144,4145],{"class":1014}," })",[1004,4147,4052],{"class":1014},[1004,4149,4150,4153,4156,4159,4161,4164,4167],{"class":1006,"line":1088},[1004,4151,4152],{"class":4032},"      if",[1004,4154,4155],{"class":1010}," (",[1004,4157,4158],{"class":1188},"token",[1004,4160,382],{"class":1014},[1004,4162,4163],{"class":1188},"value",[1004,4165,4166],{"class":1010},") ",[1004,4168,4104],{"class":1014},[1004,4170,4171,4174,4176,4179,4181],{"class":1006,"line":1120},[1004,4172,4173],{"class":1188},"        options",[1004,4175,382],{"class":1014},[1004,4177,4178],{"class":1188},"headers",[1004,4180,4063],{"class":1014},[1004,4182,4052],{"class":1014},[1004,4184,4185,4188,4191,4193,4195],{"class":1006,"line":1150},[1004,4186,4187],{"class":1014},"          ...",[1004,4189,4190],{"class":1188},"options",[1004,4192,382],{"class":1014},[1004,4194,4178],{"class":1188},[1004,4196,4130],{"class":1014},[1004,4198,4199,4202,4204,4207,4210,4213,4215,4217,4219],{"class":1006,"line":1158},[1004,4200,4201],{"class":1010},"          Authorization",[1004,4203,175],{"class":1014},[1004,4205,4206],{"class":1014}," `",[1004,4208,4209],{"class":1017},"Bearer ",[1004,4211,4212],{"class":1014},"${",[1004,4214,4158],{"class":1188},[1004,4216,382],{"class":1014},[1004,4218,4163],{"class":1188},[1004,4220,4221],{"class":1014},"}`\n",[1004,4223,4224],{"class":1006,"line":1167},[1004,4225,4226],{"class":1014},"        }\n",[1004,4228,4229],{"class":1006,"line":1175},[1004,4230,4231],{"class":1014},"      }\n",[1004,4233,4234],{"class":1006,"line":1183},[1004,4235,4236],{"class":1014},"    },\n",[1004,4238,4239,4242,4244,4247,4249],{"class":1006,"line":1197},[1004,4240,4241],{"class":1010},"    onResponseError",[1004,4243,4138],{"class":1014},[1004,4245,4246],{"class":4141}," response",[1004,4248,4145],{"class":1014},[1004,4250,4052],{"class":1014},[1004,4252,4253,4255,4257,4260,4262,4264,4267,4271,4273],{"class":1006,"line":4002},[1004,4254,4152],{"class":4032},[1004,4256,4155],{"class":1010},[1004,4258,4259],{"class":1188},"response",[1004,4261,382],{"class":1014},[1004,4263,1033],{"class":1188},[1004,4265,4266],{"class":1014}," ===",[1004,4268,4270],{"class":4269},"sbssI"," 401",[1004,4272,4166],{"class":1010},[1004,4274,4104],{"class":1014},[1004,4276,4278,4281,4283,4285,4288,4290],{"class":1006,"line":4277},16,[1004,4279,4280],{"class":4066},"        navigateTo",[1004,4282,4070],{"class":1010},[1004,4284,4073],{"class":1014},[1004,4286,4287],{"class":1017},"\u002Flogin",[1004,4289,4073],{"class":1014},[1004,4291,4081],{"class":1010},[1004,4293,4295],{"class":1006,"line":4294},17,[1004,4296,4231],{"class":1014},[1004,4298,4300],{"class":1006,"line":4299},18,[1004,4301,4302],{"class":1014},"    }\n",[1004,4304,4306,4309],{"class":1006,"line":4305},19,[1004,4307,4308],{"class":1014},"  }",[1004,4310,4081],{"class":1010},[1004,4312,4314],{"class":1006,"line":4313},20,[1004,4315,4316],{"class":1014},"}\n",[37,4318,4320],{"id":4319},"刷新-token-的陷阱","刷新 token 的陷阱",[10,4322,4323,4324,732],{},"很多教程只讲 access token，不讲 refresh token。实际生产环境里，",[51,4325,4326],{},"没有 refresh token 的 JWT 方案是不完整的",[10,4328,4329],{},"关键设计：",[177,4331,4332,4335,4342],{},[180,4333,4334],{},"access token：15 分钟有效期，放在内存或 cookie",[180,4336,4337,4338,4341],{},"refresh token：7 天有效期，",[51,4339,4340],{},"必须"," HttpOnly cookie，防止 XSS 窃取",[180,4343,4344],{},"刷新接口：服务端校验 refresh token，签发新的 access token",[37,4346,4347],{"id":4347},"总结",[10,4349,4350],{},"JWT 认证看似简单，但实际落地有不少细节。希望这篇文章能帮你避开常见的坑。",[2250,4352,4353],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":734,"searchDepth":735,"depth":735,"links":4355},[4356,4357,4358,4359,4360],{"id":3888,"depth":735,"text":3889},{"id":3918,"depth":735,"text":3919},{"id":4008,"depth":735,"text":4009},{"id":4319,"depth":735,"text":4320},{"id":4347,"depth":735,"text":4347},"\u002Fimages\u002Ftravel\u002Fhome-placeholder-1.jpg","2026-04-10","从前端登录到后端校验，一套可落地的最佳实践，包括刷新 token、跨域 cookie 和前后端错误处理的细节。",{},"\u002Fblogs\u002Fnuxt-dotnet-jwt-auth",{"title":3883,"description":4363},"blogs\u002Fnuxt-dotnet-jwt-auth",[4369,4370,4371],"Nuxt",".NET","Auth","zTBCAyICqoS0EMy1UunGXyWApv3FEjl9Jpg1kjGcs6Y",1786331541187]