|
| 1 | +# Best Practices for Awesome-Free Project |
| 2 | + |
| 3 | +This document outlines comprehensive best practices for the awesome-free project. These guidelines ensure high-quality code, reliable data curation, and ethical maintenance of the free services collection. The practices are tailored to the project's focus on curating legitimate free-tier cloud services while maintaining technical excellence and community trust. |
| 4 | + |
| 5 | +## Project Philosophy and Values |
| 6 | + |
| 7 | +### Core Mission |
| 8 | +Provide a single source of truth for developers, creators, and builders to discover and strategically combine free offerings into production-grade systems without vendor lock-in or unexpected costs. |
| 9 | + |
| 10 | +### Core Values |
| 11 | +1. **Accuracy** - Only cite official docs or credible sources < 6 months old |
| 12 | +2. **Completeness** - Include gotchas, regional constraints, and cost traps (not just benefits) |
| 13 | +3. **Usability** - Services organized by category, easy to search and compare |
| 14 | +4. **Currency** - Flag outdated entries; automated weekly freshness checks |
| 15 | +5. **Community** - Welcoming contributions; clear guidelines for additions/updates |
| 16 | +6. **No Ads/Affiliates** - Pure curation, no sponsor preference or affiliate links |
| 17 | + |
| 18 | +### What We Cover |
| 19 | +- **Infrastructure**: Compute, databases, storage, networking (AWS, GCP, Azure, Oracle, Cloudflare, Fly.io, Railway, etc.) |
| 20 | +- **Application Platforms**: Web hosting, serverless, FaaS (Vercel, Netlify, Render, Fly.io, Heroku alternatives) |
| 21 | +- **Developer Tools**: CI/CD, monitoring, testing, security scanning (GitHub Actions, Sentry, Datadog, etc.) |
| 22 | +- **Communication**: Email, SMS, chat APIs (SendGrid, Mailgun, Twilio, Discord) |
| 23 | +- **AI/ML**: Model hosting, inference, fine-tuning (Hugging Face Spaces, Replicate, Together AI) |
| 24 | +- **Creative Tools**: Open-source software with free tiers (Blender, GIMP, Krita, etc.) |
| 25 | +- **Web3/Blockchain**: If applicable (IPFS, Arweave, etc.) |
| 26 | + |
| 27 | +### What We DON'T Cover |
| 28 | +- Services with no free tier whatsoever |
| 29 | +- Illegal or pirated software |
| 30 | +- Services requiring Darkweb access |
| 31 | +- Spam/scam services |
| 32 | +- Abandoned projects (no updates > 2 years) |
| 33 | + |
| 34 | +## Code Quality Standards |
| 35 | + |
| 36 | +### DRY (Don't Repeat Yourself) |
| 37 | +- Eliminate code duplication by creating reusable functions for common operations |
| 38 | +- Extract shared validation logic into utility modules |
| 39 | +- Use configuration files instead of hardcoding repeated values |
| 40 | + |
| 41 | +**Example**: Instead of duplicating URL validation regex across multiple scripts, create a `validators.py` module with a `validate_url()` function used by link_checker.py and validate.py. |
| 42 | + |
| 43 | +### YAGNI (You Ain't Gonna Need It) |
| 44 | +- Implement only features that are immediately needed |
| 45 | +- Avoid speculative features like advanced analytics unless requested |
| 46 | +- Focus on core functionality: service validation, data export, and documentation generation |
| 47 | + |
| 48 | +**Example**: Don't add complex filtering options to export tools until users specifically request them. Start with basic JSON/CSV export functionality. |
| 49 | + |
| 50 | +### Single Responsibility Principle |
| 51 | +- Keep functions small and focused on one task |
| 52 | +- Create separate modules for distinct concerns (validation, export, generation) |
| 53 | +- Avoid monolithic scripts that handle multiple unrelated operations |
| 54 | + |
| 55 | +**Example**: Split `validate.py` into focused functions: `validate_service_schema()`, `validate_service_links()`, `validate_service_freshness()` instead of one large validation function. |
| 56 | + |
| 57 | +### Code Readability and Maintainability |
| 58 | +- Use descriptive variable and function names that explain purpose |
| 59 | +- Add docstrings to all public functions with parameters, return values, and examples |
| 60 | +- Write self-documenting code with clear logic flow |
| 61 | + |
| 62 | +**Example**: |
| 63 | +```python |
| 64 | +def validate_service_freshness(service_data: Dict[str, Any], max_age_days: int = 90) -> bool: |
| 65 | + """Validate that service documentation was checked within the specified timeframe. |
| 66 | +
|
| 67 | + Args: |
| 68 | + service_data: Service definition dictionary |
| 69 | + max_age_days: Maximum allowed age in days for freshness checks |
| 70 | +
|
| 71 | + Returns: |
| 72 | + True if service is fresh, False if it needs re-checking |
| 73 | + """ |
| 74 | + last_checked = service_data.get('metadata', {}).get('last_verified') |
| 75 | + if not last_checked: |
| 76 | + return False |
| 77 | + # Implementation... |
| 78 | +``` |
| 79 | + |
| 80 | +## Code Structure and Organization |
| 81 | + |
| 82 | +### Modular Architecture |
| 83 | +- Organize code into logical packages: `validators/`, `exporters/`, `generators/` |
| 84 | +- Keep the root tools/python/ directory flat with clear entry points |
| 85 | +- Use relative imports for internal modules |
| 86 | + |
| 87 | +**Example Structure**: |
| 88 | +``` |
| 89 | +tools/python/ |
| 90 | +├── validators/ |
| 91 | +│ ├── __init__.py |
| 92 | +│ ├── service_validator.py |
| 93 | +│ └── link_validator.py |
| 94 | +├── exporters/ |
| 95 | +│ ├── __init__.py |
| 96 | +│ ├── json_exporter.py |
| 97 | +│ └── csv_exporter.py |
| 98 | +├── generators/ |
| 99 | +│ ├── __init__.py |
| 100 | +│ └── markdown_generator.py |
| 101 | +├── main scripts like validate.py, export_json.py, etc. |
| 102 | +``` |
| 103 | + |
| 104 | +### Consistent Naming Conventions |
| 105 | +- Use snake_case for modules, functions, and variables |
| 106 | +- Use PascalCase for classes (e.g., `ServiceValidator`) |
| 107 | +- Prefix private functions with underscore (e.g., `_validate_url_format()`) |
| 108 | +- Use descriptive names: `check_service_links()` instead of `validate()` |
| 109 | + |
| 110 | +### Configuration Management |
| 111 | +- Store configuration in dedicated files (config.yaml, settings.py) |
| 112 | +- Use environment variables for sensitive or environment-specific settings |
| 113 | +- Avoid hardcoding paths, URLs, or thresholds in code |
| 114 | + |
| 115 | +**Example**: Create `config/settings.py` with: |
| 116 | +```python |
| 117 | +DEFAULT_MAX_LINK_AGE_DAYS = 90 |
| 118 | +SUPPORTED_CATEGORIES = ['compute', 'storage', 'database', 'cdn-edge'] |
| 119 | +OFFICIAL_DOCS_TIMEOUT = 30 # seconds |
| 120 | +``` |
| 121 | + |
| 122 | +## Error Handling and Logging |
| 123 | + |
| 124 | +### Structured Error Handling |
| 125 | +- Use specific exception types instead of generic Exception |
| 126 | +- Implement proper error propagation in async operations |
| 127 | +- Provide meaningful error messages for debugging |
| 128 | + |
| 129 | +**Example**: |
| 130 | +```python |
| 131 | +class ValidationError(Exception): |
| 132 | + """Raised when service validation fails.""" |
| 133 | + pass |
| 134 | + |
| 135 | +def validate_service(service_data): |
| 136 | + try: |
| 137 | + # validation logic |
| 138 | + if not service_data.get('name'): |
| 139 | + raise ValidationError("Service name is required") |
| 140 | + except KeyError as e: |
| 141 | + raise ValidationError(f"Missing required field: {e}") from e |
| 142 | +``` |
| 143 | + |
| 144 | +### Logging Standards |
| 145 | +- Use structured logging with consistent formats |
| 146 | +- Include contextual information (service name, operation type, timestamps) |
| 147 | +- Log at appropriate levels: DEBUG for detailed info, INFO for normal operations, WARNING for issues, ERROR for failures |
| 148 | + |
| 149 | +**Example**: |
| 150 | +```python |
| 151 | +import logging |
| 152 | + |
| 153 | +logger = logging.getLogger(__name__) |
| 154 | + |
| 155 | +def check_service_links(service_data): |
| 156 | + service_name = service_data['name'] |
| 157 | + logger.info(f"Checking links for service: {service_name}") |
| 158 | + |
| 159 | + for url in service_data.get('documentation', []): |
| 160 | + try: |
| 161 | + # check logic |
| 162 | + logger.debug(f"Successfully validated URL: {url}") |
| 163 | + except requests.RequestException as e: |
| 164 | + logger.warning(f"Failed to validate URL {url} for {service_name}: {e}") |
| 165 | +``` |
| 166 | + |
| 167 | +### Graceful Degradation |
| 168 | +- Handle network failures by falling back to cached data |
| 169 | +- Continue processing other services when one fails |
| 170 | +- Provide partial results when complete validation isn't possible |
| 171 | + |
| 172 | +**Example**: In link_checker.py, if a URL times out, log the error but continue checking other URLs and mark the service as needing manual review. |
| 173 | + |
| 174 | +## Domain-Specific Best Practices |
| 175 | + |
| 176 | +### Service Accuracy and Verification |
| 177 | +- Cross-reference all service claims with official provider documentation |
| 178 | +- Verify free tier limits, features, and restrictions against multiple sources |
| 179 | +- Document verification sources and dates in service metadata |
| 180 | + |
| 181 | +**Example**: For a storage service claiming "5GB free", check the official pricing page, terms of service, and user forums to confirm the exact limits and any hidden costs. |
| 182 | + |
| 183 | +### When Uncertain Guidelines |
| 184 | +- Mark with [NEEDS_VERIFICATION] |
| 185 | +- Cite the source (even if you're unsure) |
| 186 | +- Flag in metadata for community review |
| 187 | +- Ask for official documentation link |
| 188 | +- Don't guess on limits or pricing |
| 189 | +- Check the service's official pricing page first |
| 190 | + |
| 191 | +### Free Tier Integrity |
| 192 | +- Flag any service requiring payment information for "free" access |
| 193 | +- Verify that free tiers are truly unlimited in time (not time-limited trials) |
| 194 | +- Document any usage limits, rate limits, or feature restrictions clearly |
| 195 | + |
| 196 | +**Example**: Reject services that require credit card verification for free signup, as this violates the "truly free" principle. Instead, highlight services with genuine free tiers like AWS Free Tier or Google Cloud Free Tier. |
| 197 | + |
| 198 | +### Community Curation |
| 199 | +- Encourage community contributions through clear contribution guidelines |
| 200 | +- Implement review processes for new service submissions |
| 201 | +- Maintain transparency about curation decisions and criteria |
| 202 | + |
| 203 | +**Example**: Use GitHub Issues for service suggestions with a template that requires submitters to provide official documentation links and verification evidence. |
| 204 | + |
| 205 | +### Contribution Workflow |
| 206 | + |
| 207 | +When you generate issues or PR templates for contributors: |
| 208 | + |
| 209 | +#### New Service |
| 210 | +- Link to schema |
| 211 | +- Checklist of required fields |
| 212 | +- Example YAML entry |
| 213 | +- Link to provider's free tier page |
| 214 | +- Request: "Create services/[category]/[service-id].yaml" |
| 215 | + |
| 216 | +#### Update Service |
| 217 | +- What changed (pricing, limits, regions)? |
| 218 | +- Updated YAML fields |
| 219 | +- New last_verified date |
| 220 | +- Note in metadata about change |
| 221 | +- Request: "Update services/[category]/[service-id].yaml" |
| 222 | + |
| 223 | +#### Broken Link |
| 224 | +- Which service/link is broken? |
| 225 | +- When did you last verify it worked? |
| 226 | +- Suggested fix |
| 227 | + |
| 228 | +### Data Integrity and Freshness |
| 229 | +- Implement automated freshness checks for service documentation |
| 230 | +- Regularly review and update service definitions based on provider changes |
| 231 | +- Archive discontinued services with clear discontinuation notices |
| 232 | + |
| 233 | +**Example**: Run weekly automated checks using freshness_check.py to identify services whose documentation hasn't been verified in 90+ days, then manually review and update as needed. |
| 234 | + |
| 235 | +### Ethical and Transparency Rules |
| 236 | +- Clearly disclose any affiliations or sponsorships |
| 237 | +- Maintain neutral, factual descriptions without marketing language |
| 238 | +- Prioritize user benefit over provider relationships |
| 239 | + |
| 240 | +**Example**: When describing services, use objective language like "Provides 5GB of free object storage" instead of promotional phrases like "The best free storage solution available". |
| 241 | + |
| 242 | +### Stack Composition |
| 243 | +- Ensure stack components are all legitimately free and compatible |
| 244 | +- Document integration requirements and potential limitations |
| 245 | +- Test stack combinations for real-world viability |
| 246 | + |
| 247 | +**Example**: For a "static site hosting stack", verify that all components (CDN, storage, CI/CD) offer free tiers that work together without requiring paid upgrades for basic functionality. |
| 248 | + |
| 249 | +### Automation and Monitoring |
| 250 | +- Automate repetitive tasks like link checking and validation |
| 251 | +- Monitor for service changes and provider policy updates |
| 252 | +- Implement alerts for validation failures or data inconsistencies |
| 253 | + |
| 254 | +**Example**: Set up GitHub Actions to run validation scripts on pull requests and weekly freshness checks, with notifications to maintainers for any failures. |
| 255 | + |
| 256 | +### Automation & Scripts |
| 257 | + |
| 258 | +When asked to generate tools: |
| 259 | + |
| 260 | +#### Validation (validate.py) |
| 261 | +- Load all YAML |
| 262 | +- Validate against schema |
| 263 | +- Check date freshness |
| 264 | +- Verify links (optional, expensive) |
| 265 | +- Report errors with line numbers |
| 266 | + |
| 267 | +#### Comparison (compare.py) |
| 268 | +- Side-by-side provider comparison |
| 269 | +- Filter by category, cost, features |
| 270 | +- Output formatted table (markdown, CSV, JSON) |
| 271 | + |
| 272 | +#### Export (export_csv.py, export_json.py) |
| 273 | +- Convert services to portable formats |
| 274 | +- Include all fields, flatten nested objects |
| 275 | +- Sort by category |
| 276 | + |
| 277 | +#### GitHub Actions (.github/workflows/) |
| 278 | +- Validate schema on every PR |
| 279 | +- Run scheduled checks (weekly for freshness) |
| 280 | +- Output nice formatting (comment on PR with results) |
| 281 | +- Cache dependencies to speed up runs |
| 282 | +- Use standard actions (actions/checkout, actions/setup-python) |
| 283 | + |
| 284 | +### Documentation Maintenance |
| 285 | +- Keep documentation synchronized with code changes |
| 286 | +- Update examples and tutorials as tools evolve |
| 287 | +- Maintain version consistency across README, docs, and code |
| 288 | + |
| 289 | +**Example**: When adding a new validation rule to validate.py, simultaneously update docs/EVALUATION_CRITERIA.md and any relevant code comments to reflect the change. |
| 290 | + |
| 291 | +## Success Criteria |
| 292 | + |
| 293 | +A successful awesome-free repo will: |
| 294 | + |
| 295 | +- Contain 200+ services within 6 months (all major cloud providers + common tools) |
| 296 | +- Have < 5% broken links (validated weekly) |
| 297 | +- Keep 95% of entries fresh (last_verified within 180 days) |
| 298 | +- Support 10+ categories (compute, database, storage, cdn, serverless, devtools, comms, ai/ml, creative, web3) |
| 299 | +- Enable users to build production systems on free tiers alone |
| 300 | +- Provide clear cost comparison (always-free vs credits vs trials) |
| 301 | +- Highlight gotchas more than benefits (balanced evaluation) |
| 302 | +- Be automated (CI/CD validates, links check, exports generate) |
| 303 | +- Be community-driven (clear contribution process, responsive reviews) |
| 304 | +- Remain vendor-neutral (no affiliate links, no sponsor bias) |
| 305 | + |
| 306 | +These best practices ensure the awesome-free project maintains high standards of quality, reliability, and ethical curation while supporting its mission of helping developers discover legitimate free cloud services. |
0 commit comments