您在 IDE 里打开一个第一次见到的项目文件夹:几十个嵌套的子文件夹,陌生的名字,没有一个文件是您自己写的。接下来要做改动:先是小幅调整页面,然后添加新的游戏。开始之前,得先弄清楚需要的文件放在哪里,项目里又有哪些规则。

一个接一个打开文件夹,指望碰巧找到目标位置,做起来很容易,但更有用的做法是先搞清楚项目的整体结构和规则。无论是一次小改动,还是以后想添加新游戏,这些认知都用得上:您需要选好文件名、找到合适的位置,再和 Claude Code 一起检查结果。

先找到项目的入口

从 IDE 面板里的文件树入手,在项目根目录找 README.md。这是一个普通的文本文件,写给人看的,不是写给程序的:通常会在里面简单说明这是个什么项目,以及怎么运行它。不过有时候里面只有项目名字,剩下的就指望您自己摸索了。人都是懒的,README 又不会自己写自己 :)

梗图:注释写得一丝不苟,README.md 却马马虎虎。

从 README 里通常能提取出三样东西:项目的用途、运行方式,以及指向更详细说明的链接 - 比如单独讲架构或代码规范的文件。对于一次小的页面改动来说,这已经足够看清大致情况了。

README 可能不存在,也可能落后于代码。把它当作一个起点就好:关于命令和文件夹的信息,还得跟项目里的实际文件核对一遍。如果描述里说的是一种结构,而文件树显示的是另一种,先把这个疑点记下来,留着检查。

这时候接入 Claude Code 会很方便:让它读一下 README,列出对您当前任务有用的路径 - 先不做任何改动,只是查找。智能体读文件比您快,还能马上推测出排行榜该去哪里找。

文件夹树能告诉您什么

来看一个学习用的例子:一个小型的浏览器游戏门户网站,带游戏展示页、计分和排行榜。它的部分目录树是这样的:

project/
├── README.md
├── package.json
├── vite.config.js
├── pages/
│   └── leaderboard.html
├── src/
│   ├── leaderboard.js
│   └── reward-flow.js
├── assets/
├── tests/
└── dist/

哪怕一行代码都还没读,这棵目录树已经能透露一些信息了:

文件夹或文件可以猜到的用途
README.md项目说明和运行方式
package.json项目的依赖和命令列表
vite.config.jsVite 的运行和构建配置
pages/浏览器打开的页面
src/源代码:页面引用的脚本
assets/图片、图标等静态文件
tests/自动化测试
dist/构建产物,自动生成

文件夹的名字是线索,不是定论。src/leaderboard.js 这个文件名看着像是要找的那个;接下来还得打开它,找到页面在哪里引入它。上面这张表描述的是各个文件夹预期承担的角色,具体还得逐一确认。比如 tests/ 存在这件事本身,并不能说明测试到底怎么跑。

另外值得区分的是:哪些是源代码,哪些是由源代码生成或者从外部装进来的。dist/ 通常是构建工具从 src/ 的内容自动生成的,而第三方依赖的文件夹(常见的名字是 node_modules/,虽然这个例子里没有)根本不是您团队的人写的。从这些地方开始读代码,基本没什么意义:改动要么在下次构建时被冲掉,要么就是改了不该直接改的别人的代码。包管理器、依赖安装和 lockfile 格式是另一个话题,这里不展开。

还有一点:例子里的文件夹划分不是标准答案。换一个项目,页面可能放在 public/,源码放在 app/。查找的思路是一样的,变的只是名字。

项目的工作规则

假设文件夹的用途您已经弄清楚了。在添加文件之前,还得搞明白这里习惯怎么做事。有的项目把所有页面都放进一个公共文件夹,有的项目让每个游戏连同自己的脚本和图片放在一起。两种做法都可以很顺手。问题出在:新游戏按第三种方式组织,却没有任何地方解释过这个决定。

先从 README 里的链接找约定。如果有 CONTRIBUTING.md 这个文件,它通常会说明怎么提交改动。文档里可能有文件放置规则,而 CLAUDE.md 里则是给智能体的说明。单独的文件夹也可能有自己的 README,补充说明这个文件夹里的内容。不用指望每个项目都齐全这一整套:有时候几条需要的规则就写在根目录的 README 里。

对于第一次改动,只要弄清楚哪些源文件可以改、这里怎么命名和放置文件、怎么运行项目和检查结果,就够了。如果说明禁止直接改构建产物,就去找对应的源文件。如果要求添加页面时同步更新说明,那就把这一步直接纳入任务。

没有书面规则的时候,看两三个类似的例子。对于新游戏,研究相邻的游戏比翻一个随便的文档文件夹更有用。相同的文件放置方式可以拿来当模板,但单单一个旧文件,还不足以证明整个项目都是这么组织的。

更麻烦的情况也会遇到:README 说页面该放进 pages/,可最近添加的几个游戏却放在别处。这时候,向项目负责人提一个具体的问题会很有用:"说明里写的是 pages/,但最近两个游戏放在了 games/。下一个该放哪里?"不要自己悄悄选一个顺眼的方案,也不要为了统一而把整棵树都搬一遍。

文件和文件夹的命名规则

命名是关于名字的约定。一个好名字能帮您在文件树里找到需要的文件,并且不用打开就能看懂它的用途。在我们这个门户网站里,leaderboard.html 一看就知道是排行榜,而 page2.html 只告诉您某人给它编的序号。

名字有含义和形式两个层面。含义回答的是"这里放的是什么",形式决定的是字母大小写和单词之间的分隔方式。比如,每日奖励页面可以有好几种命名方式:

风格文件名示例单词怎么连接
kebab-casedaily-rewards.html小写字母,单词之间用连字符
snake_casedaily_rewards.html小写字母,单词之间用下划线
camelCasedailyRewards.html第一个单词小写开头,后面的单词首字母大写
PascalCaseDailyRewards.html每个单词都首字母大写

这些是不同的写法,不是谁比谁好。如果项目里的页面都用连字符命名,新页面就沿用同样的风格。不过,不同类别的文件可以有各自的约定:大家熟悉的 README.md 没必要为了跟 HTML 页面看齐而改成小写。工具本身要求的固定文件名,同样要保留。

假设门户网站的普通文件约定用 kebab-case 风格的英文单词命名。那么 snake-preview.png 就比 img3.png 清楚得多:一看就知道是贪吃蛇的预览图。game-icons/ 这个文件夹名比 stuff/ 传达的信息多得多。leaderboard-final-new.html 这种名字,下一次改动之后很快就会过时;对于会一直使用的页面,按用途起一个稳定的名字更好。

给同一个概念选定一个固定的词。如果项目里游戏叫 games,又冒出一个叫 plays 的文件夹指代同一类东西,读者就得费劲去搞清楚两者有没有区别。也别把词缩写成 ldrbrd/ 这种让人猜谜的写法,除非项目的约定里本来就有这个缩写。

写法本身的精确度同样重要。文件名和路径必须完全一致,包括大小写:Snake.png 和 snake.png 不能当成同一个文件对待。这种错误可能在一台电脑上悄无声息,换个环境就暴露出来。在我们这个例子里,统一用小写的约定能减少这类问题。

文件夹嵌套的规则

名字选好了,接下来的问题是文件放哪里。当一个嵌套文件夹能把一组含义清晰的内容归到一起时,它才有用:比如游戏页面、某个游戏的图片、公共图标。每多一层,都应该有助于找到里面的内容。

设想另一种做法:门户网站不断变大,所有文件却都直接堆在根目录里:

project/
├── README.md
├── package.json
├── snake.html
├── tetris.html
├── leaderboard.html
├── snake.js
├── tetris.js
├── snake-preview.png
└── tetris-preview.png

东西不多的时候还能看得过来。等游戏数量涨到二十个,页面、脚本和图片就会互相干扰了。我们的门户网站已经分出了 pages/、src/ 和 assets/,所以添加游戏时顺着这个划分继续下去是合理的。下面是添加之后可能的结构片段:

project/
├── pages/
│   ├── leaderboard.html
│   └── games/
│       ├── snake.html
│       └── tetris.html
├── src/
│   ├── leaderboard.js
│   └── games/
│       ├── snake.js
│       └── tetris.js
└── assets/
    └── games/
        ├── snake/
        │   └── preview.png
        └── tetris/
            └── preview.png
IDE 里的项目目录树:页面在 pages 里,脚本在 src 里,贪吃蛇和俄罗斯方块的图片在 assets/games 里。

游戏页面归到一组,它们的脚本归到另一组。游戏名字把相关文件串在一起。图片有专属于某个游戏的文件夹,所以短短的 preview.png 就够用了:完整路径已经说明了这是谁的预览图。同一个游戏的其他图片,也能放进这个专属文件夹。

另一个极端是像 pages/portal/content/browser/games/arcade/snake/screens/main/index.html 这样的路径。想打开一个页面,得穿过好多层,而这些名字里有一部分基本没添加任何信息。如果项目里根本没有独立的门户、屏幕和分类,这种结构只会制造没有意义的工作量。

"不超过三层文件夹"这种统一的限制并不存在。要检查的是每一层的实际意义:它把什么归到了一起,是否有助于把这一组和旁边的区分开?出于工具或项目规则的要求,有时候确实需要一个只放一个文件的文件夹。但仅仅因为"以后这里可能会放点什么"就建一个文件夹,通常还为时过早。

上面的目录树展示的是我们这个例子的演变过程。如果您的项目里每个游戏已经完整地放在自己的文件夹中,那就继续沿用这个方式。新增一个游戏,本身不构成重新调整其他游戏的理由。

共用文件和局部文件放在哪里

贪吃蛇有了一张苹果的图片,整个门户网站又有一个共用的 logo。两者都属于图片,用法却不一样。苹果只有这一个游戏需要,logo 则会出现在展示页、排行榜和各个游戏页面上。

属于某个游戏的文件只在这个游戏里用到。本节里把这类文件叫作局部文件:说的是使用范围,不是存在电脑还是服务器上。按我们这棵目录树的方式,苹果的图片会放进 assets/games/snake/apple.png。共用文件是好几个部分都需要的;如果项目里约定了这样一个文件夹,logo 可以单独放进 assets/shared/portal-logo.svg。shared 这个词的意思是"共用",但文件夹的名字本身并不会给文件带来任何特殊属性。

样式和脚本也适用同样的区分。贪吃蛇游戏区域的样式属于它自己,公共头部的样式属于整个门户网站。选择放在哪里时,先问一句:现在是谁在用这个文件?不用为了将来可能的复用,提前把所有东西都塞进公共文件夹。

反过来,把同一个 logo 复制进每个游戏的文件夹也不方便:换 logo 的时候得把所有副本都找出来。如果这确实是一份共用资源,引用同一个文件会更好。而两个游戏里外观相似的图片,完全可以各自独立:外表相似,不代表它们总会一起改动。

游戏门户网站的共用和局部资源贪吃蛇、俄罗斯方块和排行榜都使用共用的 portal-logo.svg。只有贪吃蛇使用 apple.png。箭头从页面指向它们使用的文件。贪吃蛇snake.html俄罗斯方块tetris.html游戏排行榜leaderboard.htmlapple.png仅贪吃蛇使用portal-logo.svg三个页面共用使用
箭头从页面指向它们使用的资源。

在这张图里,共用 logo 有三条箭头指向它,而苹果图片只有一条。所以替换 logo 之后要检查全部三个页面,替换苹果图片之后只需要检查贪吃蛇。改动之前,不妨让 Claude Code 先找一下哪些文件引用了这个资源:实际的引用关系,可能比从文件夹名字看出来的更多。

移动和重命名时要检查什么

重命名一个文件只要一秒钟,但它原来的名字可能已经写进了链接和配置里。移动还会改变它和其他文件的相对位置。所以整理目录结构,和修改页面内容一样,都是对项目的实际改动。

来看一个单独的移动例子:页面 pages/snake.html 被移到了 pages/games/snake.html。脚本还留在原地,在 src/games/snake.js。在这个例子里,相对路径是从 HTML 页面的地址算起的。移动之后,引用需要相应修改:

<!-- 移动之前,在 pages/snake.html 里 -->
<script src="../src/games/snake.js" type="module"></script>

<!-- 移动之后,在 pages/games/snake.html 里 -->
<script src="../../src/games/snake.js" type="module"></script>

每一段 ../ 都会把路径往上提一层。现在得先从 games/ 出去到 pages/,再到根目录,然后才能进入 src/。脚本本身没有变,但旧路径已经指不对了。

反方向的引用也存在:展示页上的游戏卡片仍然可能指向那个旧的页面地址。移动之前,先在项目里查找旧路径出现的地方。移动之后,更新相关的链接、引用、构建配置和文档里的示例。对于改名的脚本,还要检查 import - 也就是其他脚本引用它的那些语句。

IDE 可能会自动更新一部分引用,但结果还是要自己过一遍。不是每个路径都写在一行里:有时候地址是由文件夹名和文件名拼出来的。所以,搜索旧名字有助于找到依赖关系,而运行对应的场景则有助于发现漏掉的地方。

怎样检查改动结果

先在项目文档里找到运行、构建和检查用的命令。如果是带 package.json 的项目,把说明和它的 scripts 部分对照一下。命令的名字因项目而异;tests/ 文件夹的存在本身,并不能说明到底该跑哪个命令。如果没有相关说明,就去问清楚检查方式,而不是随便套用一个熟悉的命令。

接下来的检查方式取决于具体改了什么。移动贪吃蛇的页面之后,通过展示页上的卡片打开它:这样能同时检查跳转和游戏本身的加载。确认图片都出现了,游戏也能正常运行。改动共用 logo 之后,还要看一下排行榜和另一个游戏页面。

构建成功是好事,但不能替代这些检查:指向旧地址的链接可能仍然留在构建产物里。把已经确认能用的地方和还没检查的地方都记下来。比如:"构建通过了,贪吃蛇能从展示页打开并正常运行;窄屏下的显示效果还没检查"。

最后,过一遍改动过的文件列表。添加一个游戏,预期会涉及它自己的文件加上展示页的改动。如果其他游戏的文件夹被重命名,或者图片被大批量重写,就需要解释一下原因。这个检查花的时间,比事后排查意外的问题要少。

怎样把规则传达给 Claude Code

"把游戏加得利落点"这种要求,留给智能体的决策空间太大了。更有效的做法是:说清任务,并让它先研究一下现有的约定。新游戏的存放路径应该跟着项目本身的结构走,而不是由智能体随便决定。

那些长期有效、已经验证过的规则,可以写进 CLAUDE.md。对于我们这个学习用的门户网站,片段大概是这样:

## 文件和文件夹
- 普通文件和文件夹用 kebab-case 风格的英文单词命名。
  README.md 和 CLAUDE.md 这两个约定俗成的名字保持不变。
- 游戏页面放在 pages/games/,游戏脚本放在 src/games/。
- 单个游戏的资源放在 assets/games/<game-name>/。
- 门户网站的共用图片放在 assets/shared/。
- 移动或重命名文件时,同步更新指向该文件的引用
  以及文件内部的相对路径。

## 检查
- 运行和检查用的命令从 README.md 里获取。
- 新游戏要从展示页打开,并确认能正常运行。
- 改动共用资源之后,检查所有用到它的页面。

这是一份已经商定好的规则示例,不是放之四海而皆准的目录模板。在自己的项目里写类似的规则之前,先把路径和命令跟实际文件核对一遍。如果智能体只是猜测了某个文件夹的用途,让它说明依据;不要把一个猜测直接变成长期指令。

现在,添加游戏的任务可以这样描述:

需要按附带的说明,给门户网站添加游戏 memory-match。
阅读 README.md、CLAUDE.md,以及本次任务会涉及的文件夹说明。
看看现有两个游戏的文件是怎么放置的。
为新页面、脚本和图片提出名字和路径方案。
指出需要修改展示页的哪个文件,以及怎样检查结果。
如果说明和项目实际结构有出入,先提问。
先给出方案,等我确认之后再动手改动。

在方案阶段就能评估具体的决策:游戏会放在哪里,哪些文件会变成共用的,会不会影响到相邻的页面。改动完成后,请智能体列出改动过的文件和做过的检查。这样您会更容易把结果和当初商定的方案对上号。