Contributing to Lokus
Thank you for your interest in contributing to Lokus! We’re building the next generation of knowledge management tools, and we welcome contributions from everyone—whether you’re fixing bugs, adding features, improving documentation, or helping with community support.
Quick Links
Ways to Contribute
Code Contributions
Bug Fixes
- Fix reported bugs
- Add test cases for bugs
- Improve error handling
- View open bug reports
New Features
- Implement requested features
- Add new plugins
- Extend existing functionality
- View feature requests
Performance Improvements
- Optimize slow operations
- Reduce memory usage
- Improve startup time
- Enhance search performance
Non-Code Contributions
Documentation
- Improve existing docs
- Write tutorials
- Add examples
- Fix typos and clarify content
- Translate documentation
Design
- Create UI mockups
- Design themes
- Improve UX flows
- Create icons and assets
Testing
- Report bugs
- Test on different platforms
- Write test cases
- Improve test coverage
Community
- Answer questions
- Help new contributors
- Write blog posts
- Create video tutorials
- Share your workflows
Getting Started
Prerequisites
Before you begin, ensure you have:
- Git installed
- Node.js 18+ and npm
- Rust toolchain (latest stable)
- Platform-specific dependencies (see below)
For detailed setup instructions, see Developer Setup.
Quick Setup
# Fork the repository on GitHub first
# Clone your fork
git clone https://github.com/YOUR_USERNAME/lokus.git
cd lokus
# Add upstream remote
git remote add upstream https://github.com/lokus-ai/lokus.git
# Install dependencies
npm install
# Run development server
npm run tauri devDev Container Setup (Recommended)
The easiest way to get started is using our Dev Container:
- Install Docker Desktop
- Install VS Code + Dev Containers extension
- Clone the repository
- Open in VS Code
- Click “Reopen in Container”
Everything will be automatically configured!
Development Workflow
1. Find Something to Work On
Good First Issues
If you’re new to the project, look for issues labeled good first issue.
Help Wanted
Check issues labeled help wanted for high-priority items.
Feature Requests Browse feature requests to find ideas.
2. Create an Issue (if needed)
Before starting work, create or comment on an issue to:
- Avoid duplicate work
- Get feedback on your approach
- Ensure the change will be accepted
For large features, consider opening an RFC (Request for Comments) in GitHub Discussions.
3. Create a Branch
# Update your main branch
git checkout main
git pull upstream main
# Create a feature branch
git checkout -b feature/your-feature-name
# Or for bug fixes
git checkout -b fix/issue-123-bug-descriptionBranch Naming Conventions:
feature/- New featuresfix/- Bug fixesdocs/- Documentation changesrefactor/- Code refactoringperf/- Performance improvementstest/- Test additions or fixeschore/- Build, CI, or tooling changes
4. Make Your Changes
Follow our coding standards and write tests for your changes.
Frontend Changes:
# Start dev server (auto-reloads)
npm run tauri dev
# Run tests in watch mode
npm run test:watchBackend Changes:
# Format Rust code
cd src-tauri
cargo fmt
# Run Clippy (linter)
cargo clippy
# Run Rust tests
cargo test5. Commit Your Changes
Follow Conventional Commits format:
git add .
git commit -m "feat: add wiki link autocomplete"
git commit -m "fix: resolve math rendering in tables"
git commit -m "docs: update installation guide"Commit Message Format:
<type>(<scope>): <subject>
<body>
<footer>Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, etc.)refactor: Code refactoringperf: Performance improvementstest: Test changeschore: Build, CI, or tooling changes
Examples:
feat(editor): add slash command for templates
fix(search): handle special characters in queries
docs(contributing): add section on commit messages
perf(graph): optimize node rendering for large graphs
test(editor): add tests for wiki link parsing6. Push Your Changes
# Push to your fork
git push origin feature/your-feature-name7. Create a Pull Request
- Go to github.com/lokus-ai/lokus
- Click “New Pull Request”
- Select your branch
- Fill out the PR template
- Submit the PR
Coding Standards
TypeScript/JavaScript
Style Guidelines
- Use ES6+ features
- Prefer functional components with hooks
- Use TypeScript types where possible
- Follow existing code patterns
Naming Conventions
// Files
ComponentName.jsx // React components
utilityName.js // Utilities
use-hook-name.js // Custom hooks
// Code
const variableName = ... // camelCase for variables
function functionName() // camelCase for functions
class ClassName // PascalCase for classes
const CONSTANT_NAME // SCREAMING_SNAKE_CASE for constantsReact Patterns
import React, { useState, useEffect, useCallback } from 'react';
const MyComponent = ({ prop1, prop2 }) => {
// 1. Hooks
const [state, setState] = useState(null);
// 2. Effects
useEffect(() => {
// Effect logic
return () => {
// Cleanup
};
}, [dependencies]);
// 3. Callbacks
const handleClick = useCallback(() => {
// Handler logic
}, [dependencies]);
// 4. Render
return (
<div className="my-component">
{/* JSX content */}
</div>
);
};
export default MyComponent;Async/Await
// Good
async function fetchData() {
try {
const response = await fetch('/api/data');
const data = await response.json();
return data;
} catch (error) {
console.error('Failed to fetch data:', error);
throw error;
}
}
// Avoid
function fetchData() {
return fetch('/api/data')
.then(response => response.json())
.then(data => data)
.catch(error => {
console.error('Failed to fetch data:', error);
throw error;
});
}Rust
Style Guidelines
- Follow Rust conventions (
cargo fmt) - Use Clippy for linting (
cargo clippy) - Write idiomatic Rust
- Document public APIs
Naming Conventions
// Files
my_module.rs // snake_case
// Code
let variable_name // snake_case for variables
fn function_name() // snake_case for functions
struct StructName // PascalCase for types
const CONSTANT_NAME // SCREAMING_SNAKE_CASE for constantsError Handling
use anyhow::{Result, Context};
// Good - use Result for error propagation
fn read_file(path: &str) -> Result<String> {
let content = std::fs::read_to_string(path)
.context("Failed to read file")?;
Ok(content)
}
// Avoid - unwrap in production code
fn read_file_bad(path: &str) -> String {
std::fs::read_to_string(path).unwrap()
}Async Code
use tokio::fs;
#[tauri::command]
async fn read_note(path: String) -> Result<String, String> {
let content = fs::read_to_string(&path)
.await
.map_err(|e| e.to_string())?;
Ok(content)
}CSS/Styling
Tailwind CSS
// Good - use Tailwind utilities
<div className="flex items-center justify-between p-4 bg-card rounded-lg">
<span className="text-lg font-semibold">Title</span>
</div>
// Use cn() for conditional classes
import { cn } from '@/lib/utils';
<div className={cn(
"base-classes",
isActive && "active-classes",
isDisabled && "disabled-classes"
)}>Custom CSS
/* Use CSS custom properties for theming */
.my-component {
background-color: hsl(var(--background));
color: hsl(var(--foreground));
border: 1px solid hsl(var(--border));
}
/* Follow BEM for custom classes */
.block {}
.block__element {}
.block--modifier {}Testing
Writing Tests
Unit Tests (Vitest)
import { describe, it, expect, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
it('renders correctly', () => {
render(<MyComponent />);
expect(screen.getByRole('button')).toBeInTheDocument();
});
it('handles click events', async () => {
const handleClick = vi.fn();
render(<MyComponent onClick={handleClick} />);
await fireEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledOnce();
});
});E2E Tests (Playwright)
import { test, expect } from '@playwright/test';
test('create and save note', async ({ page }) => {
await page.goto('/');
// Create new note
await page.click('[data-testid="new-note"]');
// Type content
const editor = page.locator('.editor');
await editor.fill('# My Note\n\nThis is a test note.');
// Save
await page.keyboard.press('Mod+S');
// Verify saved
await expect(page.locator('.status-bar')).toContainText('Saved');
});Rust Tests
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_frontmatter() {
let content = "---\ntitle: Test\n---\nContent";
let result = parse_frontmatter(content);
assert!(result.is_ok());
let (frontmatter, body) = result.unwrap();
assert_eq!(frontmatter.get("title"), Some(&"Test".to_string()));
assert_eq!(body, "Content");
}
#[tokio::test]
async fn test_async_function() {
let result = async_function().await;
assert!(result.is_ok());
}
}Running Tests
# Unit tests
npm test # Run once
npm run test:watch # Watch mode
npm run test:coverage # With coverage
# E2E tests
npm run test:e2e # Headless
npm run test:e2e:headed # With browser
npm run test:e2e:ui # Interactive UI
# Rust tests
cd src-tauri
cargo test
cargo test -- --nocapture # Show outputTest Coverage
Aim for:
- 80%+ coverage for new features
- 100% coverage for utility functions
- E2E tests for critical user paths
Pull Request Process
Before Submitting
Checklist:
- Code follows our style guidelines
- Tests pass locally
- New tests added for new functionality
- Documentation updated (if needed)
- Commit messages follow conventions
- Branch is up to date with main
- No merge conflicts
# Update your branch
git fetch upstream
git rebase upstream/main
# Run all checks
npm test
npm run test:e2e
cd src-tauri && cargo test && cargo clippyPR Template
Our PR template will ask you to provide:
Description
- What changes were made?
- Why were these changes necessary?
- What issue does this address?
Type of Change
- Bug fix
- New feature
- Breaking change
- Documentation update
- Performance improvement
Testing
- How were changes tested?
- What platforms were tested?
- Screenshots (for UI changes)
Checklist
- Self-reviewed code
- Tests pass
- Documentation updated
- No breaking changes (or clearly documented)
Review Process
- Automated Checks: CI/CD runs tests and builds
- Code Review: Maintainers review code quality
- Discussion: Address feedback and questions
- Approval: At least one maintainer approval required
- Merge: Squash and merge to main
Response Time
- Initial response: 1-3 days
- Full review: 3-7 days
- Complex PRs may take longer
Addressing Feedback
# Make requested changes
git add .
git commit -m "fix: address review feedback"
git push origin feature/your-feature-name
# For fixup commits
git commit --fixup=<commit-hash>
git rebase -i --autosquash upstream/mainAfter Merge
- Your PR branch will be automatically deleted
- Changes will be included in the next release
- You’ll be added to contributors list
- Consider helping review other PRs!
Documentation
Writing Documentation
MDX Files
---
title: Page Title
description: Brief description for SEO
keywords: [keyword1, keyword2, keyword3]
---
# Page Title
Brief introduction paragraph.
## Section
Content with examples...Code Examples
Use triple backticks for code blocks:
```javascript
// Example code
const greeting = "Hello, World!";
console.log(greeting);
```Links
- Internal: [Page Title](/path/to/page)
- External: [Example](https://example.com)
- Anchor: [Section](#section-id)Documentation Types
User Documentation
- Getting started guides
- Feature explanations
- Tutorials and workflows
- Troubleshooting
Developer Documentation
- Architecture overviews
- API references
- Plugin development guides
- Contributing guidelines
Community Guidelines
Code of Conduct
We follow a Code of Conduct based on the Contributor Covenant. Key points:
Be Respectful
- Use welcoming and inclusive language
- Respect differing viewpoints
- Accept constructive criticism gracefully
Be Collaborative
- Help others learn and grow
- Share knowledge freely
- Credit others’ work
Be Professional
- Focus on what’s best for the project
- Maintain professionalism in discussions
- Handle disagreements constructively
Communication Channels
GitHub Issues
- Bug reports
- Feature requests
- Task tracking
GitHub Discussions
- General questions
- Ideas and RFC
- Show and tell
- Announcements
Discord
- Real-time chat
- Community support
- Off-topic discussions
- Security issues: security@lokusmd.com
- Private matters: team@lokusmd.com
Getting Help
Stuck on something?
- Check existing documentation
- Search GitHub issues
- Ask in Discord #development channel
- Create a discussion on GitHub
Found a bug?
- Search existing issues
- Create a new issue with details
- Provide reproduction steps
- Include system information
Advanced Topics
Working with Git
Keeping Your Fork Up to Date
# Add upstream remote (once)
git remote add upstream https://github.com/lokus-ai/lokus.git
# Update your fork
git fetch upstream
git checkout main
git merge upstream/main
git push origin mainInteractive Rebase
# Clean up commits before PR
git rebase -i upstream/main
# Commands in rebase:
# pick - keep commit
# reword - edit message
# squash - combine with previous
# drop - remove commitResolving Conflicts
# Update branch
git fetch upstream
git rebase upstream/main
# Resolve conflicts in files
# Then continue rebase
git add .
git rebase --continue
# Force push (only to your branch!)
git push origin feature/your-feature-name --force-with-leaseBuilding Plugins
See our comprehensive Plugin Development Guide for:
- Plugin structure
- API documentation
- Examples and templates
- Publishing process
Performance Optimization
Profiling
# React Profiler
# Use React DevTools Profiler tab
# Rust Profiling
cargo install flamegraph
cargo flamegraph --bin lokusBenchmarking
// Vitest benchmarks
import { bench, describe } from 'vitest';
describe('performance', () => {
bench('function to test', () => {
// Code to benchmark
});
});Cross-Platform Testing
Local Testing
# macOS
npm run build:macos
# Windows (on Windows)
npm run build:windows
# Linux
npm run build:linuxGitHub Actions
- All PRs run on Windows, macOS, and Linux
- Automated testing and building
- Results show in PR checks
Release Process
Versioning
We follow Semantic Versioning:
- MAJOR (1.0.0): Breaking changes
- MINOR (0.1.0): New features (backwards compatible)
- PATCH (0.0.1): Bug fixes
Release Cycle
- Development: Changes merged to main
- Version Bump: Update version numbers
- Changelog: Update CHANGELOG.md
- Tag: Create git tag
- Build: Automated builds for all platforms
- Release: GitHub release with artifacts
- Announcement: Community announcement
Release Schedule
- Major releases: Quarterly
- Minor releases: Monthly
- Patch releases: As needed
Recognition
Contributors are recognized through:
README
- All contributors listed
- Significant contributions highlighted
Release Notes
- Feature contributions credited
- Bug fixes acknowledged
All Contributors Bot
- Automatically recognizes contributions
- Includes code, docs, design, etc.
FAQ
How do I become a maintainer?
Maintainers are chosen based on:
- Consistent high-quality contributions
- Community involvement
- Code review participation
- Technical expertise
Can I work on multiple issues?
Yes, but please:
- Finish existing PRs first
- Don’t hoard issues
- Communicate your progress
What if my PR isn’t merged?
Not all PRs are merged. Reasons include:
- Doesn’t fit project direction
- Implementation concerns
- Duplicate functionality
- Needs significant changes
We’ll provide feedback and work with you to improve PRs when possible.
How do I report security issues?
DO NOT create public issues for security vulnerabilities.
Email security@lokusmd.com with:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)
Can I use AI tools (like Copilot)?
Yes, AI tools are welcome for:
- Code completion
- Boilerplate generation
- Documentation writing
But ensure you:
- Understand the generated code
- Test thoroughly
- Follow our standards
- Own the contribution
Resources
Documentation
External Resources
Community
Thank You!
Your contributions make Lokus better for everyone. Whether you’re fixing a typo or implementing a major feature, every contribution is valued.
Happy contributing! 🚀
Questions? Join our Discord or start a Discussion.