展示HN:使用Claude Code 氛围编码书架
Show HN: Vibe coding a bookshelf with Claude Code

原始链接: https://balajmarius.com/writings/vibe-coding-a-bookshelf-with-claude-code/

## 从混乱到数字书架:AI与品味的力量 多年来,一个超过500本书的个人图书馆一直未编目,并非缺乏意愿,而是因为执行过程过于繁琐。最终,随着AI代理的出现,这个看似简单的项目才得以实现。最初使用标准ISBN扫描应用程序尝试失败,因为无法处理非标准版本,这凸显了需要一个容忍不完美的系统。 解决方案是拍摄每本书,并利用Claude编写脚本,使用OpenAI的视觉API提取元数据。虽然实现了90%的准确率,但作者专注于手动纠正剩余的错误——这是一个判断,优先考虑完成而非追求绝对完美。类似的迭代改进也发生在书封面处理上,使用了API,最终对晦涩的书籍使用了Photoshop。 真正的突破不在于代码本身(全部由AI生成),而在于作者角色的转变。AI处理了*实施*,而作者专注于*品味*——选择基于书脊的可视化方式,而不是简单的网格,拒绝了无限滚动等不必要的功能,并不断完善动画,直到它们*感觉*合适为止。 这次经历表明,随着执行成本的下降,人类的判断力和审美感将成为关键的差异化因素。最终的结果是一个功能齐全且视觉上吸引人的数字书架,证明了以人类洞察力引导的AI辅助创作的力量。

一场 Hacker News 的讨论围绕着使用 Claude Code 进行“氛围编码”,Claude Code 是一种用于软件开发的 AI 工具。用户普遍认为它擅长较小、独立的项目,例如构建一个书架应用程序——本质上是为单个用户设计的软件。 关键在于,目前的 LLM 在处理大型、复杂项目时面临上下文限制和过度设计解决方案(通过添加不必要的抽象)的倾向。Claude Code 最好的用法不是完全自动化编码,而是用于*执行*,而人类则保留*意图和品味*——指导整体设计并确保代码符合特定需求。 一位用户指出,Claude Code 弥合了那些理解软件结构但缺乏日常编码能力的人之间的差距,从而大大缩短了个人项目和变通方案的开发时间。它尤其适用于一次性脚本和简单的 Web 应用程序。
相关文章

原文

I own more books than I can read. Not in a charming, aspirational way, but in the practical sense that at some point I stopped knowing what I owned. Somewhere around 500 books, memory stopped being a reliable catalog.

For years, I told myself I would fix this. Nothing elaborate, nothing worthy of a startup idea. A spreadsheet would have been enough. I never did it, not because it was hard, but because it was tedious.

Part of my personal library
Part of my personal library

The gap between intention and execution was small, but it was enough to keep the project permanently parked in the someday pile.

By the end of 2025, I had been working with AI agents long enough that this kind of project finally felt possible. Not because they made things more impressive, but because they removed the part I always stalled on. Execution.

The bookshelf project is where I clearly understood what my role becomes once execution stops being the bottleneck.

The problem

I tried the obvious tools first. ISBN scanner apps failed on Romanian editions, and Goodreads could not identify obscure publishers or antiquarian finds. Anything even slightly nonstandard came back incomplete or wrong. Partial data felt worse than no data at all, so every attempt ended the same way: a few entries filled in, followed by abandonment.

What I needed was not a better app, but a way to tolerate imperfection without the whole system falling apart.

The data

Every project starts with bad data, and this one started with worse data. One afternoon, I photographed every book I own: spines, covers, duplicates, and the occasional blurry thumb. Four hundred and seventy photos in total. Once the images were on my laptop, I opened Claude.

470 shots, one afternoon
470 shots, one afternoon

The first steps were mechanical. Renaming files. Converting HEIC to JPG. Then I asked for something real: a script that sends each image to OpenAI's vision API, extracts author, title, and publisher, normalizes names, resizes images to avoid wasting tokens, and writes everything to a JSON file.

Claude wrote the script and ran it. It worked. Not perfectly, but well enough to matter.

{
  "id": "ZfEPBCMZDaCKm6k0NVJ8F",
  "title": "Simulacre și simulare",
  "author": "Jean Baudrillard",
  "publisher": "Colectia Panopticon",
  "source": "dataset/83.jpg",
},

Roughly 90 percent of the books came back correct. The failures were predictable: poor lighting, damaged covers, unreadable spines. One novel was confidently identified as a 1987 Soviet agricultural manual.

I fixed the rest by hand. That decision was not technical, it was judgment. Ninety percent accuracy was enough. Chasing the remaining ten percent would have meant days of edge cases for very little additional value. That was the first moment where my role became clear.

Later, when I received a few books for Christmas, we added a second script that runs the same pipeline for new additions. Photo in, metadata and images out.

The covers

With metadata sorted, covers were still missing. My photos showed spines, not artwork, and I wanted a clean visual representation. Claude suggested using Open Library's API to fetch covers, which mostly worked. Half the covers were low quality or incorrect, and Romanian editions barely existed in the database.

We iterated. Claude wrote a second pass, another model call that scored cover quality and flagged bad matches. For flagged books, it fell back to Google Images via SerpAPI. That handled most cases. A few remained: antiquarian finds and obscure Soviet boxing manuals that no database was ever going to have clean assets for.

I opened Photoshop and fixed ten covers by hand. For a collection of 460 books, ten manual edits felt like a win.

The shelf

Once the data and covers were in place, the UI came next. The obvious solution was a grid of covers. It was correct, and it was lifeless. I kept looking at my physical bookshelf instead. What makes it interesting is not the covers, but the spines. Different widths, uneven pressure, colors blending into a single texture.

The shelf, version zero
The shelf, version zero

That was the thing I wanted to recreate.

Claude did not invent that idea. It executed it. It wrote a script to extract dominant colors from each cover using color quantization, then computed contrasting text colors for readability. The result was better, but still wrong. Every book had the same width, and real books are not like that.

Open Library had page counts. We mapped page count to spine width and added slight variation to break the uniformity. At that point, it finally looked like a bookshelf.

{
  "id": "ZfEPBCMZDaCKm6k0NVJ8F",
  "title": "Simulacre si simulare",
  "author": "Jean Baudrillard",
  "backgroundColor": "#f0f0ff",
  "color": "#1f1f2e",
  "paddingLeft": 13,
  "paddingRight": 13,
  "height": 384,
  "cover": "/images/bookshelf/[email protected]",
  "source": "dataset/83.jpg"
},

The animation

Visually, the shelf worked, but it felt static. A real shelf responds to touch. When you run your finger along the spines, they tilt slightly. I asked Claude for an animation, and it came back with a scroll based tilt using Framer Motion.

It was close, but wrong. The movement snapped instead of flowing. I did not know why, I just knew it felt off. That was enough.

Claude explained the issue immediately. We were updating React state on every scroll event, causing unnecessary re renders. The fix was to use motion values and springs that animate outside React's render cycle. Two minutes later, it was fixed. I spent the next few minutes scrolling back and forth, just watching it move. This was the moment my caution dropped, not because the tool was always right, but because the cost of trying ideas had collapsed.

Killing good code

That confidence had a downside. I started asking for things I did not need. Infinite scroll seemed sensible. Why render 460 books at once? Claude implemented it, and technically it worked. Memory stayed flat, and the DOM updated correctly.

But scrolling broke. The container height desynced, the last books were unreachable, and every attempted fix introduced new jank. The feature worked, but the experience did not. So we removed it. Not because it was broken, but because it was unnecessary. Four hundred and sixty books is not a scale problem. Knowing when to delete working code is not something an AI can decide for you.

The stack view

The shelf looked great on desktop, but on mobile, horizontal scrolling felt cramped. I wanted an alternative layout: books lying flat, stacked vertically, readable without tilting your head. I pointed Claude at the shelf implementation and asked for a stack view.

Stack UI on mobile
Stack UI on mobile

It read the code, inferred the patterns, and reused them: animation timing, color extraction, scroll based opacity, the same data shape. It built the new component and wired up a toggle between layouts. It worked without explanation. That surprised me more than anything else.

What I actually did

Claude wrote all the code. So what did I do?

  • I decided that 90 percent accuracy was enough.
  • I fixed the ten covers no API could find.
  • I rejected a grid because I wanted spines.
  • I deleted infinite scroll because I did not need it.
  • I kept scrolling the animation until it felt right.

Claude handled implementation. I handled taste.

After years of false starts, my bookshelf finally exists. Four hundred and sixty books, cataloged and displayed at bookshelf. I almost dismissed Claude Code as hype. Now, the times when I wrote everything by hand feel distant, almost strange.

Execution keeps getting cheaper. Taste still does not.

联系我们 contact @ memedata.com