Thank you for your interest in contributing to RUXAILAB! This document provides guidelines and instructions for contributing to this open-source usability testing platform.
- Code of Conduct
- Getting Started
- Development Setup
- Contribution Workflow
- Code Standards
- Testing
- Reporting Issues
- Issue Labeling Guide
- Pre-commit Hooks
We are committed to providing a welcoming and inclusive environment for all contributors. Please be respectful and constructive in all interactions.
For Code of Conduct discussions and support, please use our Discord channel: https://discord.com/channels/1209902463239593984/1209902463713288293
RUXAILAB is a Vue.js-based platform for usability testing and heuristic evaluation. Before contributing, familiarize yourself with:
- Node.js ≤ 24.12.0
- Python 3.11.8
- npm (comes with Node.js)
- Docker (optional, for Firebase Emulators)
This approach runs the entire application with Firebase emulators in Docker containers.
-
Clone the repository
git clone https://github.com/uramakilab/remote-usability-lab.git cd remote-usability-lab -
Set up environment variables
cp .env.example .env
Update
.envwith the following for local emulator development:DEBUG=true PORT=8000 VUE_APP_FIREBASE_API_KEY=YOUR_API_KEY VUE_APP_FIREBASE_AUTH_DOMAIN=YOUR_PROJECT_ID.firebaseapp.com VUE_APP_FIREBASE_STORAGE_BUCKET=YOUR_PROJECT_ID.appspot.com VUE_APP_FIREBASE_DB_URL=http://localhost:9000 VUE_APP_FIREBASE_PROJECT_ID=YOUR_PROJECT_ID VUE_APP_FIREBASE_MESSAGING_SENDER_ID=YOUR_SENDER_ID VUE_APP_FIREBASE_APP_ID=YOUR_APP_ID VUE_APP_I18N_LOCALE=en VUE_APP_I18N_FALLBACK_LOCALE=en
-
Build and run with Docker
docker compose build docker compose up
-
Access the application
- Application: http://localhost:8080
- Firebase Emulator UI: http://localhost:4000
For development with a real Firebase project:
-
Clone and install dependencies
git clone https://github.com/uramakilab/remote-usability-lab.git cd remote-usability-lab npm install -
Create Firebase project
- Go to Firebase Console
- Create a new project
- Enable Realtime Database, Firestore, Authentication, and Storage
-
Configure environment
- Get your Firebase config from Project Settings
- Copy
.env.exampleto.env - Fill in your Firebase credentials
-
Run development server
npm run serve
Fork the repository and clone your fork:
git clone https://github.com/YOUR_USERNAME/remote-usability-lab.git
cd remote-usability-labBranch from develop:
git checkout develop
git pull origin develop
git checkout -b feature/your-feature-nameBranch naming conventions:
feature/- New featuresfix/- Bug fixesdocs/- Documentation updatesrefactor/- Code refactoringtest/- Adding or updating tests
- Write clean, readable code
- Follow the existing code style
- Add tests for new functionality
- Update documentation as needed
Use clear, descriptive commit messages:
git add .
git commit -m "feat: add user profile customization"Commit message format:
feat:- New featurefix:- Bug fixdocs:- Documentation changesstyle:- Formatting, missing semicolons, etc.refactor:- Code restructuringtest:- Adding testschore:- Maintenance tasks
git push origin feature/your-feature-nameThen create a Pull Request on GitHub:
- Target the
developbranch - Provide a clear description of your changes
- Reference any related issues
- Keep at most 2 open Pull Requests per contributor at any time (additional PRs are automatically closed by workflow)
- Wait for review and address any feedback
We use Prettier for code formatting. Prettier is automatically applied through pre-commit hooks, so you don't need to manually format most of the time.
# If needed, manually format files
npx prettier --write src/your-file.vueSee Code Formatting Rules section below for detailed information about formatting standards.
We use ESLint for code quality. Configuration is in eslint.config.mjs.
# Run linter
npm run lint
# Auto-fix issues
npm run lint:fixSee Code Formatting Rules section below for detailed ESLint configuration information.
- Use Composition API for new components
- Follow Vue 3 style guide
- Use Vuetify components consistently
- Keep components small and focused
- Use proper prop validation
src/
├── app/
│ ├── components/ # Reusable components
│ ├── plugins/ # Vue plugins (Firebase, etc.)
│ ├── router/ # Vue Router configuration
│ └── views/ # Page components
├── features/ # Feature-specific modules
├── shared/ # Shared utilities and constants
└── store/ # State management
# Run all tests
npm run test:unit
# Run tests in watch mode
npm run test:unit:watch
# Run with coverage
npm run test:unit:coverage# Run E2E tests
npm run test:e2e
# Run in headed mode (see browser)
npm run test:e2e:headed- Write unit tests for utility functions and components
- Write E2E tests for critical user flows
- Aim for good coverage without over-testing
- Keep tests maintainable and readable
Each contributor may have a maximum of 5 open issues at a time.
When reporting bugs, please include:
- Clear title describing the issue
- Steps to reproduce the bug
- Expected behavior vs actual behavior
- Environment details (OS, browser, Node version)
- Screenshots if applicable
- Error messages or console logs
Use the Bug Report template
For feature requests, include:
- Use case - Why is this feature needed?
- Proposed solution - How should it work?
- Alternatives considered - Other approaches you've thought about
Use the Feature Request template
For questions or general discussion, use GitHub Discussions.
Issues in RUXAILAB are automatically labeled based on the issue title format and content. Understanding how labels work helps with issue organization and discoverability.
Issues are automatically labeled when opened or edited. Here's how to use labels effectively:
Use conventional commit prefixes in your issue title to get proper type labels:
| Prefix | Label | Usage |
|---|---|---|
feat: |
feature |
New features or enhancements |
fix: |
bug |
Bug reports and fixes |
docs: |
documentation |
Documentation improvements |
refactor: |
refactor |
Code refactoring |
test: |
tests |
Test additions or improvements |
perf: |
performance |
Performance improvements |
ci: |
ci |
CI/CD workflow changes |
chore: |
chore |
Maintenance tasks |
build: |
build |
Build system changes |
style: |
style |
Formatting and style changes |
Examples:
- ✅
feat: add dark mode support→ getsfeaturelabel - ✅
fix: correct navbar alignment→ getsbuglabel - ✅
docs: update installation guide→ getsdocumentationlabel - ❌
Add dark mode support→ no type label (ambiguous)
maintainer-issue- Issues opened by maintainers and team memberscommunity-issue- Issues opened by community contributors
These labels help maintainers identify which issues come from the core team vs. the community.
bug- Auto-applied for bug reports (if title contains[bug],🐞, or matches bug template)help- Auto-applied if issue title or body mentions "help wanted" or "need help"
Some labels are applied manually by maintainers:
good first issue- Good starting points for new contributorsblocked- Issues blocked by other workwontfix- Issues that won't be worked onduplicate- Duplicate of another issuepriority-high/priority-medium/priority-low- Issue priority levelssecurity- Security-related issuesdependencies- Dependency update issues
To ensure your issue gets the correct labels:
-
Use conventional commit format for the title:
<type>(<scope>): <description>type: One of feat, fix, docs, refactor, test, perf, ci, chore, build, stylescope(optional): Component or area affected, e.g.,auth,dashboarddescription: Brief description
Examples:
feat(auth): add social login providersfix(ux-creation): resolve template duplication bugdocs(api): update Firebase setup instructions
-
Use issue templates: GitHub provides templates for bug reports and feature requests that auto-apply some labels
-
Be clear and descriptive: This helps maintainers understand the issue scope and apply additional labels correctly
This project uses Husky and lint-staged to automatically format and lint code before each commit. This ensures code quality standards are maintained.
When you commit changes, the following automatically runs:
- Husky intercepts the commit
- lint-staged runs linting and formatting on staged files:
- ESLint checks for code quality issues
- Prettier formats code for consistency
# Files matching src/**/*.{js,vue} will have:
- eslint --fix # Auto-fix ESLint issues
- prettier --write # Auto-format with PrettierPre-commit hooks are set up automatically when you run:
npm installThis installs Husky and sets up the .husky/pre-commit hook.
If pre-commit hooks aren't running, initialize Husky:
npx husky installIf you absolutely need to skip the pre-commit hook, use:
git commit --no-verifyYou can also manually run these commands:
# Check for ESLint issues
npm run lint
# Auto-fix ESLint issues
npm run lint:fix
# Format code with Prettier (if needed manually)
npm run format
# Or use Prettier directly to format specific files
npx prettier --write src/your-file.vueRUXAILAB uses Prettier for consistent code formatting. While there's no .prettierrc file, Prettier uses sensible defaults:
- Print Width: 80 characters
- Tabs: 2 spaces (no tabs)
- Quotes: Double quotes for strings
- Semicolons: Enabled
- Trailing Commas: ES5 style (where valid in older JS)
- Arrow Functions: Always add parentheses around parameters
ESLint configuration is in eslint.config.mjs:
- Parser: Uses Vue 3 template parser with Babel support
- Plugins: Vue, Vuetify, Vue I18n
- Extends: Vue recommended rules, Vuetify recommendations, Prettier integration
- Browsers Globals: Browser APIs are available
Key rules enforced:
- Vue 3-specific syntax requirements
- Proper component structure
- No unused variables
- Proper i18n usage
<template>
<div class="card">
<h2>{{ title }}</h2>
<p>{{ description }}</p>
<v-btn @click="handleClick">{{ buttonText }}</v-btn>
</div>
</template>
<script setup>
import { computed, ref } from 'vue'
const props = defineProps({
title: {
type: String,
required: true,
},
description: {
type: String,
default: '',
},
})
const emit = defineEmits(['click'])
const count = ref(0)
const buttonText = computed(() => {
return count.value > 0 ? `Clicked ${count.value} times` : 'Click me'
})
function handleClick() {
count.value++
emit('click', count.value)
}
</script>
<style scoped>
.card {
padding: 1rem;
border: 1px solid var(--divider);
border-radius: 4px;
}
</style>// Use const by default, let if you need to reassign
const API_ENDPOINT = 'https://api.example.com'
let selectedUser = null
// Arrow functions for callbacks
const items = data.map((item) => ({
...item,
formatted: item.value.toUpperCase(),
}))
// Destructuring in function parameters
function processData({ name, age, email }) {
return {
name: name.trim(),
age: parseInt(age),
email: email.toLowerCase(),
}
}
// Use template literals
const message = `Hello, ${userName}! You have ${messageCount} new messages.`
// Async/await for promises
async function fetchUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`)
if (!response.ok) {
throw new Error(`API error: ${response.status}`)
}
return await response.json()
} catch (error) {
console.error('Failed to fetch user:', error)
throw error
}
}- README.md - Project overview and setup
- Vue.js Documentation
- Vuetify Documentation
- Firebase Documentation
- Video Tutorial - Running RUXAILAB with Firebase Emulators
- General Questions: GitHub Discussions
- Bug Reports: GitHub Issues
- Security Issues: Contact the maintainers privately
Thank you for contributing to RUXAILAB! 🎉