Skip to content

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.


Prerequisites

  • Node.js 18 or later
  • npm 9 or later (comes with Node 18)
  • A modern browser (Chrome / Firefox / Edge / Safari) for testing

Local Development Setup

# 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

Available scripts

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 build runs vue-tsc --noEmit first. All TypeScript errors must be resolved before a PR can be merged.


Project Stack

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

Workflow

  1. Open an issue before starting significant work — describe what you want to change and why.
  2. Create a branch from main with a descriptive name:
    git checkout -b feat/my-new-preset
    git checkout -b fix/grain-intensity-clamp
  3. Make your changes following the conventions below.
  4. Test locally with npm run dev and npm run build.
  5. Open a pull request against main with a clear description of the change.

Code Conventions

TypeScript

  • 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 interface for data shapes (FilterParams, etc.) and type for unions.

Vue components

  • 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/.

Filter functions

  • Every filter function must have the signature (imageData: ImageData, params: XxxParams): void and 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.

Naming

  • Files: camelCase.ts for utilities and filters; PascalCase.vue for components.
  • Preset IDs: kebab-case strings (e.g. 'kodak-portra-400').
  • i18n keys: camelCase (e.g. 'kodakPortra400').

Commit messages

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

What to Work On

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

Reporting Bugs

Open a GitHub Issue and include:

  1. What you did
  2. What you expected
  3. What actually happened
  4. Browser and OS version
  5. A screenshot or screen recording if relevant

Clone this wiki locally