thedivergentai/godot-project-foundations
Expert blueprint for Godot 4 project organization (feature-based folders, naming conventions, version control). Enforces snake_case files, PascalCase nodes, %SceneUniqueNames, and .gitignore best practices. Use when starting new projects or refactoring structure. Keywords project organization, naming conventions, snake_case, PascalCase, feature-based, .gitignore, .gdignore.
npx skills add https://github.com/thedivergentai/GD-Agentic-Skills --skill godot-project-foundations
Feature-based organization, consistent naming, and version control hygiene define professional Godot projects.
override.cfg.RefCounted delegation.emit_changed().Logger for crash reporting.WorkerThreadPool implementation._unhandled_input buffer.> Do NOT Load dependency_auditor.gd unless troubleshooting loading errors.
/scripts, /sprites folders. Nightmare maintainability. Use feature-based: /player, /ui.%SceneUniqueNames for stable references..godot/ folder = 100MB+ bloat + conflicts..psd, .blend) in root will be imported unless ignored.duplicate(true) for unique instances with independent state.load() — Strictly use ResourceLoader.load_threaded_request() for async scene transitions.call_deferred() for thread-to-main-thread synchronization.WorkerThreadPool or Object Pool._process() for precise input — Tied to visual framerate. Strictly use _unhandled_input() to capture exact, frame-independent events.| Need | Prefer | Avoid |
|------|--------|-------|
| Everything for one feature (player, HUD panel) | Feature folder scene module | Type folders (/scripts, /sprites) |
| Cross-scene service with lifecycle (save, audio bus) | Autoload via managed_autoload.gd | Stuffing UI nodes into singletons |
| Many publishers/subscribers, no ownership | EventBus → MANDATORY global_event_bus.gd | Autoload that imports half the game |
| One scene's private wiring | Scene-local node + %UniqueName | Global bus for parent→child calls |
snake_case (C# exception: PascalCase class-match).PascalCase.snake_case; Inspector Title-Cases them._ on members and virtuals (_ready, _process).snake_case (health_changed).%SceneUniqueNames over brittle get_node() paths.Group by feature (/entities/player, /ui/main_menu), not by file type. Keep /common, /levels, /addons.
Godot-aware .gitignore (ignore .godot/) + .gdignore on raw design sources.
canvas_items + expand stretch defaults — account for in UI layout tests.project.godot exists → run project_bootstrapper.gd / create entities/, ui/, levels/, common/..gitignore + document feature-based layout in README.md.Full typed-GDScript migration lives in godot-gdscript-mastery.
For new foundations projects: Project Settings → Debug → GDScript → Untyped Declaration = Warn or Error.
MANDATORY load async_resource_loader.gd — threaded ResourceLoader with progress. Do not paste SceneManager samples here.
MANDATORY load global_event_bus.gd for typed global signals. Do not paste EventBus samples here.
Use build_metadata_provider.gd / base_data_resource.gd for version/build flags instead of ad-hoc JSON.
Full naming table, typed-GDScript migration, EventBus/SceneManager/metadata samples — references/foundations-deep.md.
> Progressive disclosure: open Official Documentation links only when researching a specific API; load Related Skills when routing to a peer domain — do not preload the whole lattice.
.gdignore, and VCS hygiene that keep imports and repos maintainable.%SceneUniqueNames beat brittle get_node() paths.Untyped Declaration → Warn/Error) when migrating foundations to GDScript 2.0.ResourceLoader.load_threaded_* patterns for non-blocking scene transitions.res:// / user:// conventions for scaffolded folders and saved override.cfg / metadata.BaseDataResource-style reactive Resources into full data-driven catalogs without shared mutation._unhandled_input buffering into full action maps and device routing..gitignore, and build metadata hooks.Take thedivergentai/godot-project-foundations from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.