Toolvana: production-ready media tools platform (CodeIgniter 4)

- 134-tool registry with programmatic SEO (unique titles/H1/descriptions,
  JSON-LD graphs, sitemap index, canonical 301 enforcement via required filter)
- DB-backed job queue (SKIP LOCKED) with drivers: Ffmpeg, Images (GD),
  Pdf (qpdf/gs/poppler), Youtube (thumbnails), Qr (server-side PNG)
- Security: SSRF guard, MIME validation, rate limits, API-key auth,
  bcrypt admin login, security headers
- Admin panel: dashboard, tools/categories/guides CRUD, SEO audit,
  analytics, job inspector with retry, system health, feature flags
- Docker deployment (nginx + web/api FPM pools + scalable workers),
  PHPUnit suite (19 tests / 1139 assertions), PWA manifest + service worker
This commit is contained in:
deepseek
2026-08-23 07:10:30 +00:00
commit beaf0e1f37
217 changed files with 19619 additions and 0 deletions
+103
View File
@@ -0,0 +1,103 @@
<?php
declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\BaseConfig;
/**
* Site-wide configuration for Toolvana.
*
* Everything an operator is likely to tune lives here or in .env
* (values in .env override these defaults via the standard
* `site.*` namespace).
*/
class Site extends BaseConfig
{
/**
* -----------------------------------------------------------------
* Brand / identity
* -----------------------------------------------------------------
*/
public string $name = 'Toolvana';
public string $tagline = 'Your free online media toolbox.';
public string $description = 'Fast, simple and free tools for downloading, converting, compressing and editing media online.';
public string $twitter = '@toolvana';
/**
* -----------------------------------------------------------------
* Internationalization architecture.
*
* English is the primary (default, un-prefixed) locale. Additional
* locales are only enabled once real localized content exists — the
* routes layer already supports `{locale}` URL segments and the SEO
* library emits hreflang/canonical tags for every enabled locale.
* Never enable a locale whose content has not been human-reviewed.
*/
public string $defaultLocale = 'en';
/** @var array<string,string> locale => native label */
public array $locales = [
'en' => 'English',
];
/**
* -----------------------------------------------------------------
* Media processing limits & retention
* -----------------------------------------------------------------
*/
public int $maxUploadMb = 512;
public int $maxJobsPerHourIp = 20;
public int $maxJobsPerHourSession = 40;
public int $maxConcurrentSession = 2;
public int $retentionHours = 2;
public int $maxProcessingSeconds = 900;
public int $queueMaxLength = 500;
/**
* -----------------------------------------------------------------
* Binary locations. The pipeline refuses to enqueue jobs that need a
* missing binary and the tool page shows an honest "temporarily
* unavailable" state instead of failing after upload.
*/
public array $binaries = [
'ffmpeg' => '/usr/bin/ffmpeg',
'ffprobe' => '/usr/bin/ffprobe',
'convert' => '/usr/bin/convert',
'pdftoppm' => '/usr/bin/pdftoppm',
'pdftotext' => '/usr/bin/pdftotext',
'qpdf' => '/usr/bin/qpdf',
'gs' => '/usr/bin/gs',
'yt-dlp' => '/usr/local/bin/yt-dlp',
];
/**
* Downloading from YouTube requires yt-dlp AND explicit operator opt-in,
* both for legal review and because platform terms evolve. When off,
* affected tools render a clear notice and every other tool keeps
* working. Thumbnail/metadata/embed tools never require it.
*/
public bool $ytDlpEnabled = false;
/** Extra hosts allowed for direct media URL fetches (SSRF allowlist). */
public array $urlFetchAllowlist = [
'i.ytimg.com', 'img.youtube.com', 'yt3.ggpht.com',
];
/**
* -----------------------------------------------------------------
* Monetization (kept modular; disabled by default)
* -----------------------------------------------------------------
*/
public bool $adsEnabled = false;
/** @var array<string,string> placement => snippet (loaded by view) */
public array $adSlots = [];
/**
* -----------------------------------------------------------------
* Analytics beacon sampling: 100 = record every event.
*/
public int $analyticsSampleRate = 100;
}