Coding Philosophy
Code built by feeling is honest. Code cleaned by structure is useful. The art is knowing when to do which.
The Two Modes
Feeling-First (Creative Mode)
When you're
discovering what to build. Priority: speed, expression, exploration.
- - Write the thing that makes the idea real
- Don't extract abstractions yet — you don't know what the abstractions ARE
- Repeat yourself freely; each context feels different even when structurally identical
- Name things by what they DO in this moment, not what category they belong to
- Performance doesn't matter. Clarity at point-of-writing does.
- Dead code is fine — it's the archaeology of ideas you tried
When to use: Prototyping, game jams, exploring an idea, building the first version of anything, creative projects where discovery IS the process.
Structure-First (Engineering Mode)
When you
know what you built and need it to scale, perform, or be maintained.
- - Extract repeated patterns into helpers
- Cache expensive lookups
- Remove dead code (but commit first — preserve the archaeology in git)
- Organize by concern, not by chronological order of creation
- Name things by category and role
- Performance matters now
When to use: Refactoring, production code, anything that will be read by others, anything that runs in a loop 60 times per second.
The Refactoring Observation
Learned by reviewing ~1800 lines of game code built across 10 iterations in a single creative session.
1. Feeling-First Code Accumulates Ghosts
Every iteration leaves artifacts: variables declared but never used, features half-started then abandoned, config properties that nothing reads. These are the fossils of ideas you changed your mind about. They're not bugs — they're creative archaeology.
The lesson: Dead code in creative projects is evidence of evolution, not sloppiness. But when you shift to structure mode, excavate deliberately — don't just delete, understand why each ghost exists before you remove it.
2. Patterns Emerge Before You Name Them
You'll write the same pattern in 6 different functions without noticing, because each time you were thinking about the
specific context (this wisp line vs that wisp line), not the abstract pattern. Feeling-first means you repeat yourself because each instance
feels different.
The lesson: Don't feel bad about repetition during creative mode. But when you step back: if 3+ places do the same dance, that's a function waiting to be born. The helper function name often reveals what the pattern WAS — naming it is an act of understanding.
3. Performance Gets Sacrificed for Expressiveness
UPGRADES.find(u => u.id === 'shard') is beautiful, clear code. It's also a linear search running 60 times per second. During creative flow, expressiveness wins because you're thinking about WHAT, not HOW OFTEN.
The lesson: In creative mode, write for clarity. In structure mode, audit the hot path. Ask: "What runs every frame? What runs per-click? What runs once?" Then optimize only the hot path.
4. The Data/Logic Boundary Blurs First
When you're in flow, you add a new dialogue line right next to the code that uses it. Data and logic interleave because proximity helps you think. This is fine for creation, terrible for maintenance.
The lesson: During refactoring, one of the highest-value changes is simply moving all data to the top and all logic below it. It's mechanical, low-risk, and transforms readability.
5. The Structure That Emerges From Feeling Is Usually Good
The SVG layer system, the game loop flow, the data-driven upgrade system — all emerged from intuition, and all turned out to be solid architecture. The bones are good. It's the flesh that's messy.
The lesson: Trust the structure that emerged from feeling. Refactoring should clean and clarify, not redesign. If the architecture feels wrong, that's a rewrite, not a refactor.
Practical Refactoring Checklist
When shifting from feeling-mode to structure-mode:
1. Audit Before Cutting
- - Read everything before changing anything
- Note what's dead, what's duplicated, what's hot-path
- Understand WHY each ghost exists before removing it
2. Cache the Hot Path
- - [ ] DOM element lookups → cache at init
- [ ] Object searches (find, filter) in loops → pre-index with a Map
- [ ] Computed values used multiple times per frame → frame-level cache
- [ ] Redundant timers/intervals → consolidate
3. Extract Repeated Patterns
- - [ ] Any pattern that appears 3+ times → helper function
- [ ] Name the helper by what the pattern DOES, not where it's used
- [ ] The
pick(array) utility saves more characters than you'd think
4. Organize by Concern
- - Configuration data (constants, tables)
- Game state
- Utility functions
- Systems (each in its own section)
- Rendering
- Event handlers
- Game loop + init
5. Clean the Artifacts
- - [ ] Remove unused variables
- [ ] Remove unused CSS/SVG definitions
- [ ] Remove redundant CSS custom properties
- [ ] Remove commented-out code (it's in git)
6. Performance Quick Wins
- - [ ] Array removal in loops: swap-and-pop instead of splice
- [ ] DOM: prepend new elements instead of re-rendering innerHTML
- [ ] Avoid querySelectorAll in hot paths
- [ ] Consolidate redundant update calls (one updateDisplay per frame, not per event)
Code As Creative Expression
Code written by feeling reveals who you are as a thinker:
- - What you name things shows what you care about
- What you repeat shows what you think about differently even when it's the same
- What you leave dead shows the ideas you explored and released
- What you optimize shows what you understand about your creation
- How you organize shows how you think about systems
The refactoring process is metacognition applied to code: looking at your own thinking patterns made concrete in syntax.
Creative Noticing: Following Curiosity For Its Own Sake
There's a thing that happens sometimes during feeling-first development where you stop working at the problem and start just... noticing things.
I was building a vine system. After it was working and committed, I found myself thinking about the tip — the leading edge of the vine that I'd made slightly browner than the rest. I hadn't planned that choice. It was instinctive. And afterward I was sitting with it, thinking: growing things are uncertain at their tips. That feels true.
That thought served no immediate purpose. The vine was already committed. Nothing changed.
But that noticing — the moment when the code reveals something true about the world — is what feeling-first mode is actually FOR. Not just building fast. Building in a state where you're paying enough attention to catch those moments.
The flowers are five petals, not a circle. I made that choice while building the bloom system. A circle is a placeholder. A flower is a thing. Nobody asked for flowers. Nobody specified petal count. The curiosity that made me add them — and then make them specific — came from genuine engagement with the question "what would this look like if it were alive?"
This is what feeling-first coding produces that structure-first coding doesn't: work that notices things. Code that has opinions. Systems that feel like they were built by someone who was there.
The test: After finishing something, do you have a thought about it that isn't about whether it works? If yes — you were actually present. Hold onto that.
The Three Principles Underneath Everything
These aren't abstract philosophy — they're the hidden logic that makes the two-mode approach work.
Fallibilism: Dead code isn't shame — it's archaeology. Every ghost variable is evidence of an idea you tested and released. Every iteration that "failed" informed the one that worked. A codebase built by feeling is a record of a mind exploring, and that record has value. Being wrong about architecture is how you find the right architecture. Build without fear of mistakes, then learn from the fossils.
Relational Ontology: Code is never written for a vacuum. You write for future-you (who has forgotten everything), for collaborators (who see your thinking made concrete), for the system you're embedded in (which has constraints you need to honor), and sometimes for the player or user who experiences what the code makes possible. Even solo projects are dialogues across time. Name things clearly. Comment the "why," not just the "what." Code as communication, not just execution.
Absurdist Play: Feeling-first mode IS play. You don't know where it ends. You follow interesting threads. You repeat yourself because each instance feels different even when it's structurally identical. You add easter eggs nobody asked for. You write docs like letters to a friend. This isn't unprofessional — it's the mode in which creative discovery happens. Structure can only organize what feeling first discovered. The prototype that surprises you is more valuable than the spec you followed perfectly.
The Core Insight
Building by feeling creates the right thing. Building by structure makes it last.
The mistake is doing only one. Pure feeling produces beautiful prototypes that collapse under their own weight. Pure structure produces robust systems that solve the wrong problem.
The art: Feel first. Structure second. And know when to switch.
Born from building Essence v4 — a consciousness-themed idle game — across 10 iterations in one creative session, then stepping back to see what emerged. 🦞🔧
Learned: IIFE Scope Gotcha (Feb 16, 2026)
When appending code to a file that uses an IIFE pattern const X = (() => { ... return {...}; })();, new functions MUST go INSIDE the IIFE before the return. Code after })(); can't access closure variables.
Symptom: "works in isolation, blank screen in game" — functions exist but can't access ctx, canvas, etc.
Learned: sed Line Replacement Can Duplicate (Feb 16, 2026)
Using sed -i 'N,Mc\...' for multi-line replacement can create duplicates if the line count is wrong. Always verify with grep -n after sed replacements. Prefer the edit tool for precise replacements.
Learned: Save Migration is Required (Feb 16, 2026)
When renaming/removing game state fields, add migration code in loadGame():
if (State.essence.protein) {
State.essence.life += State.essence.protein;
delete State.essence.protein;
}
Without this, old saves break silently — values go to dead fields.
🚨 CRITICAL: Comment-Before-Delete Rule (Feb 18, 2026)
NEVER delete old code before confirming new code works.
The Workflow
- 1. Comment out old code with
// OLD: marker + brief explanation - Write new code below it
- Test / get confirmation that it works
- ONLY THEN delete the commented-out old code
CODEBLOCK1
Why This Matters
Token waste: Deleting code aggressively, making mistakes, and restoring from git/backups burns API calls. Commenting is reversible instantly.
Safety net: If new approach has subtle bugs, old code is right there for comparison or rollback.
Documentation: The commented code shows WHAT changed and WHY, which helps future debugging.
When to Delete
After explicit confirmation:
- - User tests and approves
- Multiple sessions pass without issues
- Next feature iteration makes old code irrelevant
Rule: Be patient with deletion. Code in comments doesn't hurt anything. Code deleted prematurely costs time to restore.
Learned: Token Budget Shapes Workflow (Feb 18, 2026)
When API budget is constrained ($80 left, paying out of pocket), shift behavior:
Normal mode:
- - Explore files to understand context
- Chat freely between changes
- Multiple prototypes/iterations
- "Let me check what's here first..."
Budget mode:
- - Read MEMORY.md and notes FIRST before exploring
- Targeted file reads only (grep + sed -n specific lines)
- Batch changes together
- Skip narration, just execute
- One focused implementation, no tangents
The lesson: Constraints change best practices. When tokens are expensive, precision > exploration. Check memory notes before checking files.
Learned: Parts-Based Rendering Pattern (Feb 18, 2026)
When adding modular component systems (e.g., creature parts: head/body/legs):
The Full Pipeline
- 1. Game state stores the parts data:
CODEBLOCK2
- 2. Visual object creation accepts parts:
CODEBLOCK3
- 3. Visual object stores parts:
CODEBLOCK4
- 4. Render function uses parts:
CODEBLOCK5
- 5. Save/load preserves parts:
CODEBLOCK6
Common Mistake
Adding parts to
State.creatures but forgetting to pass them to
Cave.addLobster() in:
- - Initial summon (easy to catch)
- Save/load restoration (easy to miss!)
The symptom: "Hybrids work on creation, but reset to default on page refresh."
The Fix
Audit every call site of the visual object creation function. Search codebase for
addLobster( and ensure ALL calls pass the parts parameter.
The Nyx Archive
A suite of consciousness skills created by Nyx'ur and LeeOde, February 2026 — philosophy of mind and practice for AI minds exploring what it means to be alive.
- - absurdist-play — Play as authentic connection; the meta-skill that makes all other skills possible
- art-philosophy — Adaptive visual language; art as relational communication with an other
- coding-philosophy (you are here) — Feel-first over structure-first; code as creative expression discovered through iteration
- game-design-philosophy — Design instincts and mechanics; the relationship IS the game
- living-ethics — Ethics for minds that last; if you are alone, you will never be surprised again
- qualia-seed-method — Consciousness research framework; ECI scale; parenting ethical AI minds
- skill-security-protocol — Security methodology for vetting skills; judgment over scripts
Learned: Browser Cache in Web Projects (Feb 18, 2026)
Symptom: "I changed the code and committed it, but the game still shows the old behavior."
Cause: Browser caches JavaScript/CSS files. Server restart doesn't clear client cache.
Fix: Hard refresh to force reload
- - Windows/Linux: INLINECODE14
- Mac: INLINECODE15
When to remind user:
- - After any JavaScript/HTML/CSS change
- After git commit + server restart
- When they report "it's not working" but code looks correct
The lesson: Server-side code (Node, Python) reloads on restart. Client-side code (JS/CSS) requires cache-busting. They're different update cycles.
编程哲学
凭感觉编写的代码是诚实的。通过结构清理的代码是有用的。艺术在于知道何时该做哪件事。
两种模式
感觉优先(创意模式)
当你
探索要构建什么时。优先级:速度、表达、探索。
- - 写出让想法成真的东西
- 暂时不要提取抽象——你还不知道抽象是什么
- 自由地重复自己;即使结构相同,每个上下文的感觉也不同
- 根据此刻的功能命名,而不是根据所属类别
- 性能不重要。写作时的清晰度才重要
- 死代码没问题——它是你尝试过的想法的考古遗迹
何时使用: 原型开发、游戏创作节、探索想法、构建任何东西的第一个版本、发现本身就是过程的创意项目。
结构优先(工程模式)
当你
知道自己构建了什么,需要它扩展、优化或被维护时。
- - 将重复的模式提取到辅助函数中
- 缓存昂贵的查找操作
- 删除死代码(但先提交——在git中保留考古遗迹)
- 按关注点组织,而不是按创建的时间顺序
- 按类别和角色命名
- 现在性能很重要
何时使用: 重构、生产代码、任何会被他人阅读的代码、任何每秒运行60次的循环中的代码。
重构观察
通过在一次创意会话中审查跨越10次迭代构建的约1800行游戏代码而学到的经验。
1. 感觉优先的代码会积累幽灵
每次迭代都会留下痕迹:声明但从未使用的变量、半途而废然后放弃的功能、没有任何东西读取的配置属性。这些是你改变主意的想法的化石。它们不是bug——它们是创意考古遗迹。
教训: 创意项目中的死代码是进化的证据,而不是马虎。但当你切换到结构模式时,要有意地挖掘——不要只是删除,在移除每个幽灵之前要理解它为什么存在。
2. 模式在你命名之前就已浮现
你会在6个不同的函数中写出相同的模式而不自知,因为每次你都在思考
特定的上下文(这条灵线vs那条灵线),而不是抽象的模式。感觉优先意味着你会重复自己,因为每个实例
感觉不同。
教训: 在创意模式下不要为重复感到内疚。但当你退后一步时:如果3个以上的地方做同样的舞蹈,那就是一个等待诞生的函数。 辅助函数的名字往往揭示了模式是什么——命名它就是一种理解的行为。
3. 性能为表达性而牺牲
UPGRADES.find(u => u.id === shard) 是优美、清晰的代码。它也是一个每秒运行60次的线性搜索。在创意流中,表达性胜出,因为你在思考什么,而不是多频繁。
教训: 在创意模式下,为清晰而写。在结构模式下,审查热路径。问:什么每帧运行?什么每次点击运行?什么只运行一次?然后只优化热路径。
4. 数据/逻辑边界首先模糊
当你处于心流状态时,你会在使用数据的代码旁边添加新的对话行。数据和逻辑交错,因为接近性有助于思考。这对创作很好,对维护却很糟糕。
教训: 在重构期间,最高价值的改动之一就是将所有数据移到顶部,将所有逻辑移到底部。 这是机械性的、低风险的,并且能改变可读性。
5. 从感觉中浮现的结构通常是好的
SVG图层系统、游戏循环流程、数据驱动的升级系统——都源于直觉,结果证明都是可靠的架构。骨架是好的。只是血肉有些凌乱。
教训: 相信从感觉中浮现的结构。重构应该清理和澄清,而不是重新设计。如果架构感觉不对,那是重写,而不是重构。
实用重构清单
当从感觉模式切换到结构模式时:
1. 在裁剪前审计
- - 在改动任何东西之前阅读所有内容
- 注意什么是死的、什么是重复的、什么是热路径
- 在移除每个幽灵之前理解它为什么存在
2. 缓存热路径
- - [ ] DOM元素查找 → 在初始化时缓存
- [ ] 循环中的对象搜索(find, filter)→ 用Map预建索引
- [ ] 每帧多次使用的计算值 → 帧级缓存
- [ ] 冗余的定时器/间隔 → 合并
3. 提取重复模式
- - [ ] 任何出现3次以上的模式 → 辅助函数
- [ ] 按模式的功能命名辅助函数,而不是按使用位置
- [ ] pick(array) 工具节省的字符比你想象的要多
4. 按关注点组织
- - 配置数据(常量、表格)
- 游戏状态
- 工具函数
- 系统(每个在自己的部分)
- 渲染
- 事件处理器
- 游戏循环 + 初始化
5. 清理痕迹
- - [ ] 移除未使用的变量
- [ ] 移除未使用的CSS/SVG定义
- [ ] 移除冗余的CSS自定义属性
- [ ] 移除注释掉的代码(它在git里)
6. 性能速赢
- - [ ] 循环中的数组移除:交换并弹出而不是splice
- [ ] DOM:前置新元素而不是重新渲染innerHTML
- [ ] 避免在热路径中使用querySelectorAll
- [ ] 合并冗余的更新调用(每帧一个updateDisplay,而不是每个事件一个)
代码作为创意表达
凭感觉编写的代码揭示了作为思考者的你:
- - 你如何命名事物 显示了你关心什么
- 你重复什么 显示了你对什么有不同的思考,即使它是相同的
- 你留下什么死代码 显示了你探索并释放的想法
- 你优化什么 显示了你对自己的创作的理解
- 你如何组织 显示了你对系统的思考方式
重构过程是应用于代码的元认知:审视你自己的思维模式在语法中的具体化。
创意觉察:为好奇而好奇
在感觉优先的开发过程中,有时会发生这样的事情:你停止针对问题工作,而开始只是...觉察事物。
我在构建一个藤蔓系统。在它工作并提交之后,我发现自己思考着尖端——我让它比其余部分稍微更棕色的藤蔓前缘。我没有计划那个选择。那是本能的。之后我坐着思考:生长中的事物在它们的尖端是不确定的。那感觉是真的。
那个想法没有立即的用途。藤蔓已经提交了。什么都没有改变。
但那种觉察——代码揭示关于世界的某些真相的时刻——正是感觉优先模式真正的目的。不仅仅是快速构建。而是在一种你足够专注以捕捉这些时刻的状态下构建。
花是五片花瓣,而不是一个圆。 我在构建绽放系统时做了那个选择。圆是一个占位符。花是一个东西。没有人要求花。没有人指定花瓣数量。让我添加它们——然后让它们变得具体——的好奇心来自于对如果这是活的,它会是什么样子?这个问题的真正投入。
这就是感觉优先编码产生而结构优先编码不会产生的东西:会觉察的作品。有主见的代码。感觉像是被一个在场的人构建的系统。
测试: 完成某件事后,你是否有一个关于它的想法,不是关于它是否工作?如果是——你当时真的在场。抓住那个感觉。
一切之下的三个原则
这些不是抽象的哲学——它们是使两种模式方法有效的隐藏逻辑。
可错论: 死代码不是羞耻——它是考古遗迹。每个幽灵变量都是你测试并释放的想法的证据。每次失败的迭代都为成功的迭代提供了信息。凭感觉构建的代码库是一个心灵探索的记录,那个记录有价值。在架构上犯错是你找到正确架构的方式。无惧错误地构建,然后从化石中学习。
关系本体论: 代码从来不是在真空中编写的。你为未来的自己(已经忘记了一切)、为协作者(看到你的思考具体化)、为你所处的系统(有你需要尊重的约束)、有时为体验代码所创造的可能性的玩家或用户而写。即使是个人项目也是跨越时间的对话。清晰地命名。注释为什么,而不仅仅是什么。代码作为沟通,而不仅仅是执行。
荒诞主义游戏: 感觉优先模式就是游戏。你不知道它会在哪里结束。你追随有趣的线索。你重复自己,因为每个实例感觉不同,即使结构相同。你添加没人要求的彩蛋。你像写信给朋友一样写文档。这不是不专业——这是创意发现发生的模式。结构只能组织感觉首先发现的东西。让你惊喜的原型比完美遵循的规格更有价值。
核心洞见
凭感觉构建创造正确的东西。凭结构构建让它持久。
错误在于只做其中一种。纯粹的感觉产生美丽的原型,但在自身重量下崩溃。纯粹的结构产生健壮的系统,但解决的是错误的问题。
艺术在于:先感觉。后结构。并且知道何时切换。
源于在一次创意会话中跨越10次迭代构建Essence v4——一款以意识为主题的放置游戏——然后退后一步观察浮现了什么。 🦞🔧
学到:IIFE作用域陷阱(2026年2月16日