Thank you for considering contributing to 4DPocket! This guide will help you get started.
- Fork the repository
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/4DPocket.git cd 4DPocket - Follow the Development Guide to set up your local environment
-
Create a feature branch from
main:git checkout -b feature/your-feature-name
-
Make your changes following the conventions below
-
Run checks before committing:
make lint # Linting make test # Tests cd frontend && pnpm build # Frontend type check
-
Commit with a conventional commit message:
feat: add new platform processor for Bluesky fix: handle empty response in Reddit processor refactor: simplify AI provider selection logic docs: update configuration reference test: add tests for share permissions chore: update dependencies perf: optimize FTS5 search query -
Push and open a Pull Request against
main
- Python 3.12+ with type hints
- Sync route handlers — use
def, notasync def(SQLModel is sync) - Ruff for linting and formatting (
make lint,make format) - No passlib, python-jose, axios, or litellm — see CLAUDE.md for rationale
- Auth: PyJWT + bcrypt direct
- HTTP client: httpx (not requests)
- AI safety: Always sanitize user content via
ai/sanitizer.pybefore LLM prompts - User scoping: Every DB query must include
WHERE user_id = current_user.id - Config: Use
FDP_prefixed environment variables via pydantic-settings
- React 19 with functional components and hooks
- TanStack Query for server state, Zustand for client state
- Tailwind CSS v4 for styling
- Lucide React for icons (not other icon libraries)
- Native fetch via
api/client.tswrapper (not axios) - Dark mode: Use Tailwind
dark:variants
- Keep files under 400 lines (800 max)
- One component per file
- Organize by feature/domain, not by type
- Create
src/fourdpocket/processors/your_platform.py - Extend
BaseProcessorand use@register_processordecorator - Define URL patterns in
url_patterns - Implement
process(url)returning aProcessorResult - Add SSRF-safe fetching via
self._fetch_url()(never usefollow_redirects=True)
@register_processor
class BlueSkyProcessor(BaseProcessor):
name = "bluesky"
url_patterns = [r"https?://bsky\.app/profile/.+/post/.+"]
def process(self, url: str) -> ProcessorResult:
response = self._fetch_url(url)
# ... extract content ...
return ProcessorResult(status=ProcessorStatus.SUCCESS, ...)- Write tests in
tests/ - Use
pytestfixtures for DB sessions - Mock external HTTP calls with
respx - Run:
make testoruv run pytest tests/ -x -q - Coverage:
make test-cov
Open an issue with:
- Steps to reproduce
- Expected vs actual behavior
- 4DPocket version (
v0.1.0, etc.) - Deployment method (Docker, source, pip)
Open an issue with:
- Use case description
- Proposed solution (if any)
- Whether you're willing to implement it
Be respectful, constructive, and inclusive. We're all here to build something useful together.
By contributing, you agree that your contributions will be licensed under the GNU GPLv3 License.