Skip to main content
We’re excited to have you contribute to Papillon! This guide will help you understand our contribution process, code style, and best practices.

Before You Start

Papillon has strict guidelines about AI-generated contributions. All project contributions must come exclusively from human developers. AI assistance should only be used for consultation and explanation, not for generating code or documentation to be directly contributed.

Communication

  • Language: Use informal French (“tu” form) in all communications and code comments
  • Issues: Check if a similar issue exists before creating a new one
  • Discussions: For major changes, open an issue first to discuss your approach
  • Discord: Join our Discord community for questions and discussions

Contribution Workflow

1

Fork and clone the repository

git clone https://github.com/YOUR_USERNAME/Papillon.git
cd Papillon
2

Create a feature branch

Use Conventional Branch naming:
# Feature branch
git checkout -b feat/add-homework-notifications

# Bug fix branch
git checkout -b fix/timetable-timezone-issue

# Documentation branch
git checkout -b docs/update-setup-guide
Branch prefixes:
  • feat/ - New feature
  • fix/ - Bug fix
  • docs/ - Documentation changes
  • refactor/ - Code refactoring
  • test/ - Adding tests
  • chore/ - Maintenance tasks
3

Make your changes

  • Follow the code style guidelines
  • Write clear, descriptive commit messages
  • Test your changes on both iOS and Android
  • Update documentation if needed
4

Run quality checks

# Run linter (auto-fixes issues)
npm run lint

# Check formatting
npm run format:check

# Format code
npm run format

# Run tests
npm test
5

Commit your changes

Use Conventional Commits:
git add .
git commit -m "feat: add push notifications for homework"
Commit message format:
<type>(<scope>): <description>

[optional body]

[optional footer]
Types:
  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • style: Code style changes (formatting, etc.)
  • refactor: Code refactoring
  • test: Adding or updating tests
  • chore: Maintenance tasks
6

Push and create a Pull Request

git push origin feat/add-homework-notifications
Then create a Pull Request on GitHub with:
  • Clear title following Conventional Commits
  • Detailed description of changes
  • Screenshots/videos for UI changes
  • Testing notes

Pull Request Requirements

Before submitting a Pull Request, ensure:
  • One change per PR: Don’t bundle multiple features or bug fixes
  • Conventional Commits: All commits follow the convention
  • Code style: Passes ESLint and Prettier checks
  • Testing: Tested on both iOS and Android
  • Documentation: Updated if you changed documented parts
  • No console.log: Use the logger utility instead
  • Informal language: Use French “tu” form in user-facing text
  • Build success: App compiles without errors
Pull Requests that don’t meet these requirements will be marked as invalid until corrections are made.

Code Style

ESLint Configuration

Papillon enforces strict code style rules. Run the linter to check your code:
npm run lint
Key rules:
  • Indentation: 2 spaces (no tabs)
  • Semicolons: Required
  • Quotes: Double quotes for strings
  • Line length: 80 characters max
  • Trailing commas: ES5 style
  • Variables & Functions: camelCase
  • Components: PascalCase
  • Constants: UPPER_SNAKE_CASE
  • Private members: _prefixed
  • No var: Use const or let
  • No console: Use @/utils/logger/logger instead
  • No unused variables: Prefix with _ if intentionally unused
  • No unused imports: Automatically removed by ESLint
  • Strict equality: Use === and !==
  • No empty functions: Add a comment explaining why
  • Max depth: 4 levels of nesting
  • Strict mode: Enabled
  • Explicit types: For function parameters and return values
  • No any: Use proper types or unknown
  • Interface over type: Prefer interfaces for object shapes

Import Sorting

Imports are automatically sorted by eslint-plugin-simple-import-sort:
// ✅ Correct order (auto-sorted)
import { useEffect, useState } from "react";
import { View, Text } from "react-native";

import { Pronote } from "@/services/pronote";
import { useAccountStore } from "@/stores/account";
import { Button } from "@/ui/components/Button";

import { helper } from "./helper";

Prettier Configuration

Code formatting is handled by Prettier:
{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": false,
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "bracketSpacing": true,
  "arrowParens": "avoid"
}
Format your code:
npm run format

Component Guidelines

React Component Structure

import { useEffect, useState } from "react";
import { View, Text, Pressable } from "react-native";

import { useTheme } from "@/ui/hooks/useTheme";
import { logger } from "@/utils/logger/logger";

interface HomeworkCardProps {
  title: string;
  dueDate: Date;
  done: boolean;
  onPress?: () => void;
}

/**
 * Card component for displaying homework items.
 * 
 * @param title - The homework title
 * @param dueDate - When the homework is due
 * @param done - Whether the homework is completed
 * @param onPress - Optional callback when card is pressed
 */
export function HomeworkCard({ 
  title, 
  dueDate, 
  done, 
  onPress 
}: HomeworkCardProps) {
  const theme = useTheme();
  const [isPressed, setIsPressed] = useState(false);

  useEffect(() => {
    // Effect logic here
  }, [done]);

  const handlePress = () => {
    logger.info("Homework card pressed", "HomeworkCard");
    onPress?.();
  };

  return (
    <Pressable 
      style={styles.container}
      onPress={handlePress}
    >
      <Text style={styles.title}>{title}</Text>
      <Text style={styles.date}>{formatDate(dueDate)}</Text>
    </Pressable>
  );
}

Component Best Practices

  • Props interface: Always define a TypeScript interface for props
  • JSDoc comments: Document complex components
  • Destructure props: In function signature
  • Early returns: For conditional rendering
  • Memoization: Use React.memo() for expensive components
  • Hooks order: useState → useEffect → custom hooks → callbacks

Testing

Papillon uses Jest and React Test Renderer for testing.

Running Tests

# Run all tests
npm test

# Run tests in watch mode
npm test -- --watch

# Run tests with coverage
npm test -- --coverage

Writing Tests

import { render } from '@testing-library/react-native';
import { HomeworkCard } from './HomeworkCard';

describe('HomeworkCard', () => {
  it('renders homework title', () => {
    const { getByText } = render(
      <HomeworkCard 
        title="Math exercises" 
        dueDate={new Date()} 
        done={false} 
      />
    );
    
    expect(getByText('Math exercises')).toBeTruthy();
  });

  it('calls onPress when pressed', () => {
    const onPress = jest.fn();
    const { getByText } = render(
      <HomeworkCard 
        title="Math exercises" 
        dueDate={new Date()} 
        done={false}
        onPress={onPress}
      />
    );
    
    fireEvent.press(getByText('Math exercises'));
    expect(onPress).toHaveBeenCalled();
  });
});
While tests are encouraged, they’re not strictly required for all contributions. Focus on manual testing on both platforms.

Documentation

Update documentation when you:
  • Add new features
  • Change existing APIs
  • Modify project structure
  • Update configuration
Documentation locations:
  • README.md: Project overview and quick start
  • .github/CONTRIBUTING.md: This guide (French version)
  • docs/: Comprehensive documentation (you are here)
  • Code comments: For complex logic

Security

Never commit sensitive data like API keys, tokens, or credentials. If you discover a security vulnerability, don’t open a public issue. Instead, email [email protected].
Security guidelines:
  • Use .env files for secrets (already gitignored)
  • Store sensitive data in Expo SecureStore
  • Validate all user inputs
  • Sanitize data from external APIs
  • Keep dependencies updated

Reporting Issues

When creating an issue:
1

Check for duplicates

Search existing issues to avoid duplicates. If you find a similar issue, add a 👍 reaction instead of creating a new one.
2

Use the issue template

Fill out the provided template completely. It helps us understand and resolve issues faster.
3

Provide details

For bugs:
  • Current behavior
  • Expected behavior
  • Steps to reproduce
  • Screenshots/videos
  • Device info (OS, version, device model)
For features:
  • Clear description
  • Use cases
  • Screenshots/mockups
  • Potential implementation approach
4

Use a descriptive title

Good: “Timetable doesn’t show correct timezone for daylight savings” Bad: “Bug in timetable”

Code Review Process

What to Expect

  1. Automated checks: CI runs linting, tests, and builds
  2. Maintainer review: A team member reviews your code
  3. Feedback: You may be asked to make changes
  4. Approval: Once approved, your PR will be merged

Responding to Feedback

  • Be responsive to review comments
  • Make requested changes promptly
  • Ask questions if feedback is unclear
  • Push additional commits to the same branch
  • Mark conversations as resolved when addressed

Getting Help

Discord Community

Join our Discord for real-time help and discussions

GitHub Discussions

For longer-form questions and discussions

Documentation

Read the full documentation

Issue Tracker

Report bugs and request features

Additional Resources

Thank you for contributing to Papillon! Your contributions help make school management better for thousands of students.

Build docs developers (and LLMs) love