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
Fork and Clone the Repository
Fork the Invenicum repository and clone it locally:
git clone https://github.com/YOUR_USERNAME/invenicum.git cd invenicum
Install Flutter and Dependencies
Invenicum is built with Flutter. You’ll need:
flutter pub get
Set Up the Development Environment
Copy the environment configuration and start backend services:
cp .env.example .env docker-compose up -d
Configure your Gemini API key in the .env file for AI features.
Run the Application
# Mobile / desktop flutter run # Web flutter run -d chrome
Development Workflow
Branching Strategy
mainProduction-ready codedevelopIntegration branch for featuresfeature/*New features — e.g. feature/plugin-marketplacefix/*Bug fixes — e.g. fix/loan-date-calculationdocs/*Documentation updatesMaking Changes
Create a Feature Branch
git checkout -b feature/your-feature-name
Make Your Changes
Write clean, well-documented code following our coding standards (see below).
Test Thoroughly
flutter test
Commit Your Changes
git add . git commit -m "feat: add loan reminder notifications"
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
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
PascalCaseAssetTemplate, PluginServiceFiles
snake_caseasset_template_model.dartVariables / Functions
camelCasegetUserName, isActiveConstants
lowerCamelCasedefaultPageSizePrivate members
_ prefix_apiService// 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.
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');
});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
# 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:
<type>(<scope>): <subject> <body> <footer>
featNew feature
fixBug fix
docsDocumentation changes
styleCode style changes
refactorCode refactoring
testAdding or updating tests
choreMaintenance tasks
Examples
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
Prepare Your PR
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
Link Related Issues
Closes #123 Related to #456
Request Review
Tag relevant maintainers or team members for review.
Address Feedback
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
Next Steps
Recognition
All contributors are recognized in our:
Thank you for contributing to Invenicum! 🎉
Plugin Development