-
Notifications
You must be signed in to change notification settings - Fork 0
Contributing
Flying Pizza edited this page Apr 19, 2026
·
2 revisions
Thank you for your interest in contributing to GrainLab! This page covers the development setup, workflow, and conventions you should follow.
- Node.js 18 or later
- npm 9 or later (comes with Node 18)
- A modern browser (Chrome / Firefox / Edge / Safari) for testing
# 1. Fork and clone the repository
git clone https://github.com/seamys/grainlab.git
cd grainlab
# 2. Install dependencies
npm install
# 3. Start the dev server
npm run dev
# → http://localhost:5173| Command | Description |
|---|---|
npm run dev |
Start Vite dev server with HMR |
npm run build |
Type-check with vue-tsc then bundle for production |
npm run preview |
Serve the production build locally for final checks |
npm run buildrunsvue-tsc --noEmitfirst. All TypeScript errors must be resolved before a PR can be merged.
| Technology | Version | Role |
|---|---|---|
| Vue 3 | ^3.5 | UI framework (Composition API) |
| TypeScript | ^5.6 | Type safety |
| Vite | ^5.4 | Dev server and bundler |
| Pinia | ^2.2 | State management |
| Vue I18n | ^11.3 | Internationalization |
| JSZip | ^3.10 | Client-side ZIP for batch export |
| vite-plugin-pwa | ^1.2 | PWA manifest and service worker |
- Open an issue before starting significant work — describe what you want to change and why.
-
Create a branch from
mainwith a descriptive name:git checkout -b feat/my-new-preset git checkout -b fix/grain-intensity-clamp
- Make your changes following the conventions below.
-
Test locally with
npm run devandnpm run build. -
Open a pull request against
mainwith a clear description of the change.
- All new code must be TypeScript. Avoid
any. - Add types for function parameters and return values in the
src/filters/module. Components can lean on Vue's type inference. - Use
interfacefor data shapes (FilterParams, etc.) andtypefor unions.
- Use the Composition API with
<script setup lang="ts">. - Keep components focused. UI logic belongs in components; business logic belongs in stores or
src/filters/.
- Every filter function must have the signature
(imageData: ImageData, params: XxxParams): voidand mutate in-place. - Add a fast-exit guard at the top when the effect is disabled (e.g.
if (params.intensity === 0) return). - No async code, no side effects inside filter functions.
- Files:
camelCase.tsfor utilities and filters;PascalCase.vuefor components. - Preset IDs:
kebab-casestrings (e.g.'kodak-portra-400'). - i18n keys:
camelCase(e.g.'kodakPortra400').
Use the Conventional Commits format:
feat: add Kodachrome 64 preset
fix: clamp grain size to valid range
docs: update filter pipeline wiki page
refactor: extract color wheel into separate component
Check the GitHub Issues list for open tasks. Issues labelled good first issue are recommended for new contributors.
Common contribution areas:
- New film presets — see Adding a Film Preset
- New language translations — see Localization
- New filter effects — see Adding a Filter Effect
- Bug fixes — reproducible bugs with clear steps to reproduce
- Accessibility improvements — keyboard navigation, ARIA labels, contrast
Open a GitHub Issue and include:
- What you did
- What you expected
- What actually happened
- Browser and OS version
- A screenshot or screen recording if relevant
Using GrainLab
Developer Docs