ContributingContributing to Invenicum

CONTRIBUTING

Contributing to Invenicum

Learn how to contribute code, documentation, and improvements to the Invenicum project.

Welcome to the Invenicum contributor community! Whether you’re fixing bugs, adding features, improving documentation, or helping others — every contribution matters.


Ways to Contribute

Code Contributions

Fix bugs, add features, or improve performance

Documentation

Write guides, improve existing docs, or add examples

Issue Reports

Report bugs or suggest new features via GitHub Issues

Code Reviews

Review pull requests from other contributors

Plugins & Templates

Create extensions for the community marketplace

Community Support

Help others in discussions and issues

Getting Started

Step 01

Fork and Clone the Repository

Fork the Invenicum repository and clone it locally:

bash
git clone https://github.com/YOUR_USERNAME/invenicum.git
cd invenicum
Step 02

Install Flutter and Dependencies

Invenicum is built with Flutter. You’ll need:

Flutter SDK(latest stable)
Dart SDK(comes with Flutter)
Android Studio(or Xcode)
Docker(for backend)
bash
flutter pub get
Step 03

Set Up the Development Environment

Copy the environment configuration and start backend services:

bash
cp .env.example .env
docker-compose up -d

Configure your Gemini API key in the .env file for AI features.

Step 04

Run the Application

bash
# Mobile / desktop
flutter run

# Web
flutter run -d chrome

Development Workflow

Branching Strategy

mainProduction-ready code
developIntegration branch for features
feature/*New features — e.g. feature/plugin-marketplace
fix/*Bug fixes — e.g. fix/loan-date-calculation
docs/*Documentation updates

Making Changes

Step 01

Create a Feature Branch

git checkout -b feature/your-feature-name
Step 02

Make Your Changes

Write clean, well-documented code following our coding standards (see below).

Step 03

Test Thoroughly

flutter test
Step 04

Commit Your Changes

git add .
git commit -m "feat: add loan reminder notifications"
Step 05

Push and Create a Pull Request

Push your branch and open a PR against the develop branch on GitHub:

git push origin feature/your-feature-name

Coding Standards

Dart / Flutter Conventions

File Structure
lib/
├── core/           # Core utilities, constants, themes
├── data/           # Models, services, repositories
│   ├── models/     # Data models
│   └── services/   # API and business logic services
├── providers/      # State management (Provider pattern)
├── screens/        # UI screens/pages
└── widgets/        # Reusable UI components

Naming Conventions

Classes

PascalCase
AssetTemplate, PluginService

Files

snake_case
asset_template_model.dart

Variables / Functions

camelCase
getUserName, isActive

Constants

lowerCamelCase
defaultPageSize

Private members

_ prefix
_apiService
Code Style — Example
// Good: Clear service method with error handling
Future<List<AssetTemplate>> getUserLibrary() async {
try {
  const url = '/templates/my-library';
  final response = await _dio.get(url);

  if (response.statusCode == 200) {
    final List<dynamic> data = response.data;
    return data.map((json) => AssetTemplate.fromJson(json)).toList();
  }
  return [];
} on DioException catch (e) {
  throw _handleError(e);
}
}

// Good: Well-documented model with clear properties
class AssetTemplate {
final String id;
final String name;
final String description;
final List<CustomFieldDefinition> fields;

AssetTemplate({
  required this.id,
  required this.name,
  required this.description,
  required this.fields,
});
}

Best Practices

Use Meaningful Names
// Bad
var d = DateTime.now();
var t = getT();

// Good
var createdAt = DateTime.now();
var template = getTemplate();
Keep Functions Small

Functions should do one thing well. If a function is too long, break it into smaller ones.

// Good: Single responsibility
Future<void> installPlugin(Map<String, dynamic> pluginData) async {
await _dio.post('/plugins/install', data: pluginData);
}
Handle Errors Gracefully
try {
final template = await getTemplateById(id);
return template;
} on DioException catch (e) {
debugPrint('Error fetching template: ${e.message}');
throw Exception('Unable to load template. Please try again.');
}
Document Complex Logic
// Calculate if the plugin is owned by the current user by comparing
// GitHub usernames (case-insensitive)
final bool calculatedIsMine =
  currentUserGithub != null &&
  pluginAuthor.toLowerCase() == currentUserGithub.toLowerCase();

Testing Guidelines

Writing Tests

We use Flutter’s built-in testing framework. Every new feature should include tests.

Unit Testsservices, models, utilities
test('AssetTemplate.fromJson should parse correctly', () {
final json = {
  'id': '123',
  'name': 'Books Template',
  'description': 'Template for book collections',
  'category': 'Literature',
  'fields': [],
};

final template = AssetTemplate.fromJson(json);

expect(template.id, '123');
expect(template.name, 'Books Template');
expect(template.category, 'Literature');
});
Widget TestsUI components
testWidgets('PluginCard displays plugin info', (tester) async {
await tester.pumpWidget(
  MaterialApp(
    home: PluginCard(
      plugin: mockPlugin,
    ),
  ),
);

expect(find.text('Test Plugin'), findsOneWidget);
expect(find.text('v1.0.0'), findsOneWidget);
});

Running Tests

bash
# Run all tests
flutter test

# Run specific test file
flutter test test/services/plugin_service_test.dart

# Run with coverage
flutter test --coverage

Commit Message Guidelines

We follow Conventional Commits:

format
<type>(<scope>): <subject>

<body>

<footer>
feat

New feature

fix

Bug fix

docs

Documentation changes

style

Code style changes

refactor

Code refactoring

test

Adding or updating tests

chore

Maintenance tasks

Examples

commit messages
feat(plugins): add plugin update notification system
fix(loans): correct overdue date calculation
docs(api): update authentication endpoint documentation
refactor(templates): simplify template publishing workflow

Pull Request Process

Step 01

Prepare Your PR

Branch is up to date with developAll tests passCode follows style guidelinesCommits are clean and well-structured
Step 02

Write a Clear Description

What

Clear summary of changes

Why

Problem being solved

How

Technical approach (if complex)

Testing

How you tested the changes

Screenshots

For UI changes

Step 03

Link Related Issues

Closes #123
Related to #456
Step 04

Request Review

Tag relevant maintainers or team members for review.

Step 05

Address Feedback

Respond to all commentsMake requested changesPush updates to the same branch
Step 06

Merge

Once approved, a maintainer will merge your PR into develop.

Code Review Guidelines

For Authors

  • Be open to feedback and constructive criticism
  • Respond to comments promptly
  • Ask questions if feedback is unclear
  • Don’t take criticism personally — it’s about the code, not you

For Reviewers

  • Be respectful and constructive
  • Explain the “why” behind suggestions
  • Approve when changes meet standards
  • Focus on: correctness, code quality, performance, security, test coverage

Community Guidelines

Code of Conduct

  • Be respectful — treat everyone with kindness
  • Be collaborative — work toward the best solutions
  • Be patient — help newcomers and be understanding
  • Be constructive — provide helpful feedback
  • Be professional — keep discussions focused

Getting Help

  • Documentation — Check the docs first
  • Discussions — Use GitHub Discussions for questions
  • Issues — Search existing issues before creating new ones
  • Discord / Slack — Join community channels if available

Recognition

All contributors are recognized in our:

GitHub contributors listRelease notes (for significant contributions)Community showcase

Thank you for contributing to Invenicum! 🎉

Start of section
Next

Plugin Development