Thank you for your interest in contributing to Aether! This document provides guidelines and instructions for contributing.
Found a bug? Please open an issue with:
- A clear, descriptive title
- Steps to reproduce the issue
- Expected vs. actual behavior
- Screenshots (if applicable)
- Browser, OS, and device information
Have an idea? Open a feature request with:
- The problem your idea solves
- Your proposed solution
- Any alternatives you've considered
- How the feature fits into the project's scope
- Fork the repository
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/aether.git - Install dependencies:
npm install - Create a branch:
git checkout -b feat/your-feature-name - Develop your changes
- Test locally:
npm run dev— verify in browser - Build:
npm run build— must pass with zero errors - Commit using Conventional Commits
- Push and open a Pull Request
Commit messages must follow this format:
type(scope): description
optional longer body
Types:
| Type | When to Use |
|---|---|
feat |
New feature or enhancement |
fix |
Bug fix |
docs |
Documentation-only changes |
style |
Code style changes (formatting, whitespace, no code logic) |
refactor |
Code refactoring (no behavior change) |
perf |
Performance improvements |
chore |
Build, config, tooling changes |
ci |
CI/CD configuration changes |
Examples:
feat(fluid): add shockwave density on click
fix(palette): cap brightness normalization at 1
docs(readme): add architecture diagram
refactor(main): extract smoke rendering to function
perf(fluid): reduce advect allocations
chore(deps): update vite to 6.0.1
Scopes: fluid, palette, obstacles, main, readme, ci, deps
- TypeScript strict mode is enabled. No
anyunless absolutely necessary (add a// FIXMEcomment). - Indentation: 2 spaces
- Quotes: Single quotes
- Semicolons: Required
- Line endings: LF
- Max line length: 120 characters (soft limit)
| Type | Convention | Example |
|---|---|---|
| Variables, functions | camelCase |
mouseX, drawSmokeAscii |
| Constants | UPPER_SNAKE_CASE |
BODY_TEXT, MAX_COLS |
| Types, interfaces | PascalCase |
FluidSim, PaletteEntry |
| Private/internal | Leading _ (if needed) |
_tempBuffer |
| Files | kebab-case or camelCase |
fluid.ts, palette.ts |
- Simulation state is held in plain interfaces (
FluidSim,PaletteEntry), not classes. - Render functions take
CanvasRenderingContext2Das the first argument. - Grid coordinates use
(col, row)ordering; pixel coordinates use(x, y). - All DOM access is guarded (no server-side rendering expected, but be mindful).
Prioritized list of areas where help is most valued:
- Performance optimization — Adaptive grid resolution, faster palette lookup
- Mobile experience — Touch gesture refinements, responsive grid scaling
- Visual polish — Color themes, smoother transitions, additional font support
- New interaction modes — Draggable obstacles, configurable text content
- Accessibility — Reduced motion support, keyboard navigation
- Testing — Unit tests for simulation and layout logic
- Documentation — Inline code comments, architecture diagrams, tutorials
-
npm run buildpasses with zero errors - Changes work in latest Chrome, Firefox, and Safari
- No console errors or warnings
- Commit messages follow Conventional Commits
- Code follows the style guide above
- If adding a feature, it's documented in the README or code comments
Please read and follow our Code of Conduct.
See the README.md and CHANGELOG.md for the current project status and roadmap.
Thank you for contributing! 🎉