Join our Discord community for real-time discussions, questions, and collaboration with other contributors and maintainers.
Project Architecture
Understanding Spoo.me’s architecture will help you navigate the codebase and make meaningful contributions.Technology Stack
Backend Framework- Flask: Python web framework for handling HTTP requests
- Jinja2: Template engine for rendering HTML pages
- Gunicorn: WSGI HTTP Server for production deployment
- MongoDB: Primary database for URL storage and analytics
- Redis: Caching layer for improved performance
- uv: Modern Python package manager and project management
- Ruff: Fast Python linter and formatter
- GitHub Actions: CI/CD pipeline for automated testing
Prerequisites
Before contributing, ensure you have the following installed and basic knowledge of these technologies:Required Knowledge
Basic familiarity with:
- Python: Core language for the backend
- Flask: Web framework fundamentals
- MongoDB: NoSQL database operations
- Redis: Caching concepts (optional but helpful)
- Jinja2: Template syntax for HTML rendering
- Git/GitHub: Version control and collaboration
External Services Setup
For full functionality, you’ll need:
- MongoDB Atlas account (free tier available)
- Discord server for webhook testing (optional for basic development)
- Redis instance (local or cloud, optional for basic development)
These can be set up during the development environment setup process.
Getting Started
Follow these steps to set up your development environment and make your first contribution.Fork and Clone the Repository
You should see both
origin (your fork) and upstream (original repository) remotes.Install uv Package Manager
uv is a fast Python package installer and resolver that manages virtual environments automatically.
Configure Environment Variables
Create your local environment configuration:Add the required configuration:
Start MongoDB
Choose one of these options:
- MongoDB Atlas (Recommended)
- Local MongoDB
- Sign up for MongoDB Atlas (free tier available)
- Create a new cluster
- Add your IP address to the access list
- Create a database user
- Get your connection string and add it to
.env
MongoDB Setup Guide
Detailed MongoDB Atlas setup instructions
Run the Development Server
How to Contribute
We welcome various types of contributions. Here’s how to get started with each:🐛 Reporting Bugs
Found a bug? Help us fix it by providing detailed information.Check Existing Issues
Before creating a new issue, search existing issues to avoid duplicates.
Use Bug Report Template
Create a new issue using our bug report template, which includes:
- Bug Description: Clear, concise description of the issue
- Steps to Reproduce: Exact steps to reproduce the behavior
- Expected Behavior: What you expected to happen
- Actual Behavior: What actually happened
- Environment: OS, Python version, browser (if applicable)
- Screenshots: Visual evidence if applicable
- Additional Context: Any other relevant information
💡 Suggesting Features
Have an idea to improve Spoo.me? We’d love to hear it!Check the Roadmap
Review our project roadmap to see planned features.
Use Feature Request Template
Create a feature request including:
- Feature Summary: Brief description of the proposed feature
- Problem Statement: What problem does this solve?
- Proposed Solution: How should this feature work?
- Alternative Solutions: Other approaches you’ve considered
- Use Cases: Real-world scenarios where this would be helpful
- Implementation Ideas: Technical approach (if you have ideas)
🔧 Code Contributions
Ready to dive into the code? Here’s our development workflow.Create a Feature Branch
Use descriptive branch names:
feature/custom-aliases, fix/redis-connection, docs/api-examplesMake Your Changes
Follow these guidelines while coding:Don’t worry, even we don’t follow this guideline completely 😅, but we highly recommend you to do so. This way we can maintain a consistent codebase and make it easier for others to understand and contribute to the project.
- Write Clean Code: Follow Python PEP 8 conventions
- Add Comments: Explain complex logic and business rules
- Update Documentation: Keep docstrings and comments current
- Handle Errors: Add proper error handling and validation
- Test Your Changes: Verify functionality works as expected
Commit Your Changes
Follow our commit message conventions:
See the Style Guidelines section below for detailed commit message format.
Pull Request Guidelines
Follow these guidelines to ensure your pull request is reviewed and merged quickly.Pull Request Checklist
Before Submitting
- Code follows style guidelines and passes linting
- Changes are tested locally
- Documentation is updated if needed
- Commit messages follow our format
- Branch is up to date with main
- No merge conflicts exist
Pull Request Description
Include:
- Summary: Brief description of what you’ve changed
- Changes Made: Detailed list of modifications
- Testing: How you tested the changes
- Screenshots: Visual changes (if applicable)
- Breaking Changes: Any breaking changes (if applicable)
Review Process
- Automated Checks: GitHub Actions will run linting and tests
- Maintainer Review: A project maintainer will review your code
- Community Feedback: Other contributors may provide feedback
- Approval: Once approved, your PR will be merged
- Deployment: Changes are automatically deployed to production
Project Structure
Understanding the codebase structure will help you navigate and contribute effectively.Key Components
- Blueprints
- Utils
- Cache
- Templates
Route Handlers: Each blueprint handles specific functionality:
api.py: REST API endpointsurl_shortener.py: Core shortening logicredirector.py: URL redirectionstats.py: Analytics and statisticscontact.py: Contact form processing
Style Guidelines
Consistent code style makes the project maintainable and professional.Git Commit Messages
Follow the conventional commit format:feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, no logic changes)refactor: Code restructuring without changing functionalityperf: Performance improvementstest: Adding or updating testschore: Maintenance tasks, dependency updates
Python Code Style
Frontend Guidelines
HTML, CSS, and JavaScript files are automatically minified in production, so focus on readability and maintainability over optimization.
- Use semantic HTML elements
- Maintain consistent indentation (2 spaces)
- Add comments for complex template logic
- Use descriptive variable names in templates
- Use BEM methodology for class naming
- Group related styles together
- Add comments for complex styling
- Use CSS custom properties for theming
- Use modern ES6+ syntax
- Add JSDoc comments for functions
- Handle errors gracefully
- Use meaningful variable names
Jinja2 Templating System
Understanding Jinja2 basics will help you work with the frontend templates.Introduction to Jinja2
Jinja2 is a modern and designer-friendly templating language for Python, modelled after Django’s templates. It is fast, widely used and secure with the optional sandboxed template execution environment.File Organization:Basic Syntax:
- Templates Directory: Contains HTML files (
templates/) - Static Directory: Contains CSS, JavaScript, and images (
static/)
- Variables:
{{ variable_name }}- Renders variables sent by the server - Control Statements:
{% statement %}- Controls template flow and logic
The HTML files are rendered using the Jinja2 templating engine, which processes the template syntax and replaces it with actual data from the server.
Static File Integration
Separating static files from HTML templates makes the project more organized and easier to maintain. Static files are included using the Including Images:
url_for function.Including CSS:Static File Versioning (Critical for Production)
When you make changes to static files, you must update the version parameter to ensure changes are reflected in production.Why This Matters:
Vercel and other hosting platforms cache static files. Without version updates, your changes won’t appear on the live site.Version Update Examples:
CRITICAL: Always increment the version number (
?v=X) when you modify any static file. This ensures users see your changes immediately.Important Guidelines
Scope and Limitations:✅ Can be used in HTML templates:
{{ }}syntax for variables{% %}syntax for control statementsurl_for()function for URLs- Template inheritance and includes
- CSS files cannot access Jinja2 variables
- JavaScript files cannot use Jinja2 syntax
- Image files are static assets only
- Focus on static files (CSS, JS, images)
- Basic Jinja2 understanding helps when modifying HTML structure
- Consult Jinja2 documentation for advanced features
- New static files go in
static/<file_type>/directory - Include new files using
url_for()in templates - Always use version parameters for cache busting
Template Syntax
Variables:
{{ variable_name }}
Control Structures: {% if condition %}...{% endif %}
Comments: {# This is a comment #}URL Generation with url_for
Use Flask’s Common Flask routes in Spoo.me:
url_for function to generate URLs for routes and static files:Using
url_for ensures your links work correctly even if you change route patterns later. It’s more maintainable than hardcoding URLs.main.index: Homepage (/)api.shorten_url: API endpoint (/api/shorten)stats.url_stats: Statistics page (/stats/<short_code>)redirector.redirect_url: URL redirection (/<short_code>)static: Static files (/static/<filename>)
Additional Guidelines
Documentation
- Update Documentation: When adding features, update relevant documentation
- API Documentation: Update OpenAPI spec for API changes
- Code Comments: Explain complex business logic and algorithms
- README Updates: Keep setup instructions current
Security Considerations
- Input Validation: Always validate and sanitize user input
- Rate Limiting: Respect existing rate limits and add new ones as needed
- Environment Variables: Never hardcode sensitive information
- SQL Injection: Use parameterized queries (applies to MongoDB aggregations)
- XSS Prevention: Escape user content in templates
Performance Best Practices
- Database Queries: Optimize MongoDB queries and use indexes
- Caching: Leverage Redis caching for frequently accessed data
- API Responses: Keep API responses minimal and paginated
- Static Assets: Optimize images and minimize asset sizes
Testing Guidelines
While we don’t have formal tests yet, ensure your changes:- Work with various URL formats
- Handle edge cases gracefully
- Don’t break existing functionality
- Perform well under load
- Work across different browsers (for frontend changes)
Automated Testing with GitHub Actions
For testing integrations and validating your changes in CI/CD workflows, we provide a GitHub Action that automatically sets up the complete spoo.me environment.GitHub Action Setup Guide
Learn how to use our GitHub Action for automated testing workflows and integration testing
- Integration Testing: Test your changes against a live spoo.me instance
- Multi-Version Testing: Validate compatibility across different Python/MongoDB versions
- Load Testing: Verify performance under various conditions
- API Testing: Automate API endpoint validation
- Running pytest: Automate pytests on github actions with local spoo.me instance
This is particularly useful for testing API changes, database integrations, and performance improvements before submitting pull requests.
Getting Help
Need assistance while contributing? Here are the best ways to get help:Discord Community
Join our Discord server for real-time help, discussions, and collaboration with other contributors.
GitHub Discussions
Start discussions about features, ask questions, and share ideas with the community.
Documentation
Read through our comprehensive documentation for API details and setup guides.
Issue Tracker
Report bugs, request features, and track the status of ongoing development.
Recognition
We value all contributions to Spoo.me! Contributors are recognized through:- Contributors Page: Listed on our website and README
- Release Notes: Mentioned in release notes for significant contributions
- Discord Roles: Special contributor roles in our Discord server
Thank you for contributing to Spoo.me! Your efforts help make URL shortening better for everyone.
Ready to start contributing? Fork the repository and make your first contribution today!

