- Comprehensive commercial product documentation for BuiltByBit marketplace - 5 detailed documents covering all aspects of commercial development - Complete implementation guide with all Gemini-provided code blocks - Full marketing strategy with BuiltByBit launch materials - Comprehensive testing guide with essential test cases - Support playbook for 2-5 hours/month sustainable operations COMMERCIAL VIABILITY: - Market validated: $9,600 proven revenue (competitor analysis) - Revenue projection: $1,000-6,750 year 1 (realistic: $3,000) - Development time: 8-10 hours (Gemini provided complete code) - Break-even: 40 sales (2-3 months at realistic pace) - ROI: Even worst case justifies build (saves 120 hours/year internal use) TECHNICAL ARCHITECTURE: - Backend: PHP/Laravel services (ModpackDetector, CacheService, 3 API providers) - Frontend: React/TypeScript status badge component - Database: Idempotent installation scripts (install.sh, remove.sh) - Platforms: CurseForge, Modrinth, FTB (Feed The Beast) - Caching: Egg Variable storage for performance - Auto-detection: File fingerprinting with graceful fallbacks PRODUCT FEATURES: - Standard tier ($14.99): CurseForge + Modrinth, manual checking - Professional tier ($24.99): + FTB + cron automation + Discord webhooks - Zero-click monitoring (status badges on dashboard) - Auto-detection (no manual configuration) - Manual override capability - Graceful API failure handling DOCUMENTATION COMPLETE: 1. README.md - Executive summary, architecture, strategy (11.6KB) 2. IMPLEMENTATION-PLAN.md - All code blocks organized by component (16.9KB) 3. MARKETING-STRATEGY.md - BuiltByBit launch materials, SEO copy (16.7KB) 4. TESTING-GUIDE.md - QA procedures, test cases, beta testing (13.7KB) 5. SUPPORT-PLAYBOOK.md - Operations guide, sustainable support (15.2KB) MARKET POSITIONING: - Unique value: MONITORING tool (competitors only install) - Solves Day 2-365 problem (maintenance, not setup) - Complementary to existing installers (not competitive) - Professional tier features unique to market (cron automation) RESEARCH SOURCE: - Complete Gemini Pro research session (4 hours, February 22, 2026) - Competitor analysis, technical architecture, commercial strategy - Operations planning, marketing materials, support strategy - Compressed months of traditional planning into single night This commercial product is READY TO BUILD when resources available. Expected execution: 8-10 hours assembly + testing + launch. Built by: The Chronicler #21 Research partner: Gemini Pro For: Firefrost Gaming (internal use) + BuiltByBit marketplace (passive income) Purpose: Generate $1,000-6,750/year passive revenue while solving internal need Fire + Frost + Foundation = Where Innovation Generates Income
16 KiB
MODPACK VERSION CHECKER - IMPLEMENTATION PLAN
Complete code implementation organized by component
All code blocks provided by Gemini Pro research session (February 22, 2026)
📋 TABLE OF CONTENTS
- Blueprint Configuration
- Database Installation Scripts
- Backend Services (PHP/Laravel)
- Frontend Components (React/TypeScript)
- API Provider Implementations
- Caching & Detection Services
- Configuration Files
1. BLUEPRINT CONFIGURATION
blueprint.yml
Location: /blueprint.yml
info:
name: "Modpack Version Monitor"
identifier: "modpackmonitor"
description: "Automated version tracking for CurseForge, FTB, and Modrinth."
version: "1.0.0"
target: "alpha"
# UI Injection Configuration
injections:
- target: resources/scripts/components/server/ServerDetailsBlock.tsx
find: <p className={"text-xs text-neutral-400 font-mono overflow-hidden text-ellipsis"}>
replace: |
<ModpackStatusBadge serverId={server.id} />
<p className={"text-xs text-neutral-400 font-mono overflow-hidden text-ellipsis"}>
Purpose: Defines extension metadata and UI injection points for Blueprint framework
2. DATABASE INSTALLATION SCRIPTS
install.sh - Database Injection Script
Location: /scripts/install.sh
Block 1: Initial Setup & Environment Parsing
#!/bin/bash
# Blueprint Extension Install Script: Modpack Checker
PTERO_DIR="/var/www/pterodactyl"
if [ ! -f "$PTERO_DIR/.env" ]; then
echo "❌ Error: Pterodactyl .env not found. Aborting."
exit 1
fi
get_env() {
grep -w "$1" $PTERO_DIR/.env | cut -d '=' -f2 | tr -d '"' | tr -d "'"
}
Block 2: Variable Assignment
echo "Loading database credentials..."
DB_HOST=$(get_env "DB_HOST")
DB_PORT=$(get_env "DB_PORT")
DB_NAME=$(get_env "DB_DATABASE")
DB_USER=$(get_env "DB_USERNAME")
DB_PASS=$(get_env "DB_PASSWORD")
Block 3: SQL Payload for MODPACK_PLATFORM
SQL_PLATFORM="INSERT INTO egg_variables
(egg_id, name, description, env_variable, default_value, user_viewable, user_editable, rules, created_at, updated_at)
SELECT id, 'Modpack Platform', 'Detected platform (auto, curseforge, ftb, modrinth)', 'MODPACK_PLATFORM', 'auto', 1, 1, 'required|string|max:50', NOW(), NOW()
FROM eggs WHERE NOT EXISTS (
SELECT 1 FROM egg_variables ev WHERE ev.egg_id = eggs.id AND ev.env_variable = 'MODPACK_PLATFORM'
);"
Block 4: SQL Payload for MODPACK_ID
SQL_ID="INSERT INTO egg_variables
(egg_id, name, description, env_variable, default_value, user_viewable, user_editable, rules, created_at, updated_at)
SELECT id, 'Modpack ID', 'Project ID for the platform', 'MODPACK_ID', '', 1, 1, 'nullable|string|max:191', NOW(), NOW()
FROM eggs WHERE NOT EXISTS (
SELECT 1 FROM egg_variables ev WHERE ev.egg_id = eggs.id AND ev.env_variable = 'MODPACK_ID'
);"
Block 5: Execution & Error Handling
echo "Injecting Modpack Platform variable..."
mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "$SQL_PLATFORM"
if [ $? -ne 0 ]; then
echo "❌ Failed to inject MODPACK_PLATFORM. Aborting."
exit 1
fi
echo "Injecting Modpack ID variable..."
mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "$SQL_ID"
echo "✅ Blueprint extension installed successfully! 🔥❄️"
remove.sh - Clean Uninstall Script
Location: /scripts/remove.sh
Block 1: Setup & Deletion
#!/bin/bash
# Blueprint Extension Remove Script
PTERO_DIR="/var/www/pterodactyl"
get_env() {
grep -w "$1" $PTERO_DIR/.env | cut -d '=' -f2 | tr -d '"' | tr -d "'"
}
DB_NAME=$(get_env "DB_DATABASE")
DB_USER=$(get_env "DB_USERNAME")
DB_PASS=$(get_env "DB_PASSWORD")
Block 2: Safely Execute Removal
echo "Removing database variables..."
SQL_REMOVE="DELETE FROM egg_variables WHERE env_variable IN ('MODPACK_PLATFORM', 'MODPACK_ID');"
mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "$SQL_REMOVE"
if [ $? -eq 0 ]; then
echo "🗑️ Modpack variables safely removed."
else
echo "❌ Error removing database variables. Manual cleanup required."
fi
Note: CASCADE foreign keys automatically clean server_variables table
3. BACKEND SERVICES (PHP/LARAVEL)
ModpackDetector.php - File Scanning & Platform Detection
Location: /app/Services/Extensions/ModpackVersionChecker/ModpackDetector.php
Block 1: Service Setup
<?php
// app/Services/Extensions/ModpackDetector.php
namespace Pterodactyl\Services\Extensions;
class ModpackDetector {
private const PLATFORMS = [
'ftb' => 'instance.json',
'modrinth' => 'modrinth.index.json',
'curseforge' => 'manifest.json',
];
}
Block 2: File Scanning Logic
public function detect(Server $server) {
foreach (self::PLATFORMS as $type => $file) {
// Check if file exists in server root
if ($this->disk->exists($server->uuid . '/' . $file)) {
return $this->processPlatform($type, $server, $file);
}
}
return 'unknown';
}
Block 3: CurseForge Extraction
private function parseCurseForge($content) {
$data = json_decode($content, true);
return [
'id' => $data['projectID'] ?? null,
'version' => $data['version'] ?? 'unknown'
];
}
Block 4: FTB Extraction
private function parseFTB($content) {
$data = json_decode($content, true);
return [
'id' => $data['modpackId'] ?? null,
'version' => $data['versionId'] ?? 'unknown'
];
}
ModpackCacheService.php - Egg Variable Caching
Location: /app/Services/Extensions/ModpackVersionChecker/ModpackCacheService.php
Block 1: Service Setup
<?php
// app/Services/Extensions/ModpackCacheService.php
namespace Pterodactyl\Services\Extensions;
use Pterodactyl\Models\Server;
class ModpackCacheService {
protected $detector;
public function __construct(ModpackDetector $detector) {
$this->detector = $detector;
}
}
Block 2: Reading the Cache
public function getCachedPlatform(Server $server) {
$platformVar = $server->variables()
->whereHas('variable', function ($query) {
$query->where('env_variable', 'MODPACK_PLATFORM');
})->first();
return $platformVar ? $platformVar->server_value : 'auto';
}
Block 3: The Detection Trigger
public function resolvePlatform(Server $server) {
$current = $this->getCachedPlatform($server);
if ($current === 'auto') {
$detected = $this->detector->detect($server);
$this->updateCache($server, $detected['platform'], $detected['id']);
return $detected['platform'];
}
return $current;
}
Block 4: Writing to Database (Caching)
private function updateCache(Server $server, $platform, $id) {
$server->variables()->whereHas('variable', fn($q) =>
$q->where('env_variable', 'MODPACK_PLATFORM')
)->update(['server_value' => $platform]);
$server->variables()->whereHas('variable', fn($q) =>
$q->where('env_variable', 'MODPACK_ID')
)->update(['server_value' => $id]);
}
4. FRONTEND COMPONENTS (REACT/TYPESCRIPT)
ModpackStatusBadge.tsx - React Component
Location: /resources/scripts/components/server/ModpackStatusBadge.tsx
Block 1: Component Setup
// resources/scripts/components/server/ModpackStatusBadge.tsx
import React, { useState, useEffect } from 'react';
import getModpackStatus from '@/api/server/getModpackStatus';
export default ({ serverId }: { serverId: string }) => {
const [status, setStatus] = useState('Checking...');
const [color, setColor] = useState('bg-yellow-500');
// Fetch logic goes here
};
Block 2: Component Render
// resources/scripts/components/server/ModpackStatusBadge.tsx (continued)
return (
<div className="flex items-center mt-2">
<span className={`px-2 py-1 rounded text-xs text-white ${color}`}>
Modpack: {status}
</span>
<button onClick={forceRescan} className="ml-2 text-xs text-gray-400 hover:text-white">
🔄 Re-scan
</button>
</div>
);
Note: Complete implementation requires API endpoint for fetching status and re-scan trigger
5. API PROVIDER IMPLEMENTATIONS
FtbApiService.php - FTB API Integration
Location: /app/Services/Extensions/ModpackVersionChecker/Providers/FtbApiService.php
<?php
// app/Services/FtbApiService.php
namespace Pterodactyl\Services\Extensions;
use Illuminate\Support\Facades\Http;
class FtbApiService {
protected $baseUrl = 'https://api.modpacks.ch/public';
public function getLatestVersion($modpackId) {
// Fetch modpack details
$response = Http::get("{$this->baseUrl}/modpack/{$modpackId}");
if ($response->successful()) {
$versions = $response->json('versions');
// FTB versions are usually ordered; grab the first (newest)
return $versions[0]['name'] ?? 'Unknown';
}
return null;
}
}
API Endpoint: https://api.modpacks.ch/public/modpack/{modpackId}
Authentication: None required (public API)
Notes:
- FTB returns version ID (integer) separately from version string
- Requires two API calls for full version info
- No rate limiting on public endpoints
CurseForgeProvider.php - CurseForge API Integration
Location: /app/Services/Extensions/ModpackVersionChecker/Providers/CurseForgeProvider.php
Structure:
<?php
namespace Pterodactyl\Services\Extensions\Providers;
class CurseForgeProvider implements ModpackProviderInterface {
protected $apiKey;
protected $baseUrl = 'https://api.curseforge.com/v1';
public function __construct($apiKey) {
$this->apiKey = $apiKey;
}
public function detectPlatform($serverPath) {
// Check for manifest.json
}
public function getInstalledVersion($serverPath) {
// Parse manifest.json
}
public function getLatestVersion($projectId) {
// Query CurseForge API
}
public function compareVersions($installed, $latest) {
// Semantic version comparison
}
}
API Requirements:
- Requires API key (user-provided)
- Store globally in admin panel
- Graceful degradation if no key
ModrinthProvider.php - Modrinth API Integration
Location: /app/Services/Extensions/ModpackVersionChecker/Providers/ModrinthProvider.php
Structure:
<?php
namespace Pterodactyl\Services\Extensions\Providers;
class ModrinthProvider implements ModpackProviderInterface {
protected $baseUrl = 'https://api.modrinth.com/v2';
// No API key needed - public API
public function detectPlatform($serverPath) {
// Check for modrinth.index.json
}
public function getInstalledVersion($serverPath) {
// Parse modrinth.index.json
}
public function getLatestVersion($projectId) {
// Query Modrinth API (no auth)
}
public function compareVersions($installed, $latest) {
// Version comparison
}
}
API Advantages:
- No authentication required
- Fast and reliable
- Modern API design
6. PROVIDER INTERFACE
ModpackProviderInterface.php
Location: /app/Services/Extensions/ModpackVersionChecker/Providers/ModpackProviderInterface.php
<?php
namespace Pterodactyl\Services\Extensions\Providers;
interface ModpackProviderInterface {
/**
* Detect if this platform's files exist in server directory
*/
public function detectPlatform(string $serverPath): bool;
/**
* Extract installed version from manifest file
*/
public function getInstalledVersion(string $serverPath): ?string;
/**
* Query platform API for latest version
*/
public function getLatestVersion(string $projectId): ?string;
/**
* Compare installed vs latest version
* Returns: 'current', 'outdated', or 'unknown'
*/
public function compareVersions(string $installed, string $latest): string;
}
Purpose: Ensures all providers implement consistent interface for detection, version extraction, and comparison
7. DIRECTORY STRUCTURE
Complete Blueprint extension file structure:
modpack-version-checker.blueprint/
├── blueprint.yml
├── scripts/
│ ├── install.sh
│ └── remove.sh
├── app/
│ └── Services/
│ └── Extensions/
│ └── ModpackVersionChecker/
│ ├── ModpackDetector.php
│ ├── ModpackCacheService.php
│ └── Providers/
│ ├── ModpackProviderInterface.php
│ ├── CurseForgeProvider.php
│ ├── ModrinthProvider.php
│ └── FtbApiService.php
├── resources/
│ └── scripts/
│ └── components/
│ └── server/
│ └── ModpackStatusBadge.tsx
└── README.md
8. IMPLEMENTATION WORKFLOW
Step 1: Create Extension Skeleton
mkdir -p modpack-version-checker.blueprint
cd modpack-version-checker.blueprint
mkdir -p scripts app/Services/Extensions/ModpackVersionChecker/Providers
mkdir -p resources/scripts/components/server
Step 2: Create Configuration Files
- Copy
blueprint.yml(from above) - Create
install.sh(all 5 blocks) - Create
remove.sh(all 2 blocks)
Step 3: Implement Backend Services
- Create
ModpackDetector.php(all 4 blocks) - Create
ModpackCacheService.php(all 4 blocks) - Create
ModpackProviderInterface.php - Create
FtbApiService.php - Create
CurseForgeProvider.php(skeleton) - Create
ModrinthProvider.php(skeleton)
Step 4: Implement Frontend Component
- Create
ModpackStatusBadge.tsx(both blocks) - Add API endpoint for status fetching
- Add re-scan trigger logic
Step 5: Test Locally
- Build Blueprint package:
blueprint -build - Test on clean Pterodactyl VPS (NOT Firefrost nodes)
- Verify all test cases pass
Step 6: Polish & Launch
- Complete documentation
- Beta test with 3-5 users
- Create BuiltByBit listing
- Launch
9. CRITICAL IMPLEMENTATION NOTES
Database Safety
The install.sh script is IDEMPOTENT:
- Uses
WHERE NOT EXISTSclause - Safe to run multiple times
- Won't duplicate variables
- Won't break existing servers
CASCADE foreign keys:
- Deleting
egg_variablesauto-deletesserver_variables - Clean uninstall with no orphaned data
API Key Management
CurseForge API Key Strategy:
- Store globally in admin panel (one key for all users)
- Graceful degradation if no key (Modrinth/FTB still work)
- Show yellow badge: "CurseForge API Key Required"
Never use shared key from developer:
- Risk: Rate limiting affects ALL customers
- Risk: Negative BuiltByBit reviews
- Solution: User provides their own key
React vs Blade
CRITICAL: Pterodactyl Client panel uses React, NOT Blade
- Admin panel = Blade (PHP)
- Client panel = React (TypeScript)
- UI injection must use React components
Caching Performance
Why Egg Variables?
- Fast database reads vs slow file scans
- Pterodactyl-native (no custom tables)
- User-editable (manual override)
- Persistent across panel updates
Cache invalidation:
- User-controlled (force re-scan button)
- No automatic re-scanning (prevents infinite loops)
- Manual override in Startup tab
10. TESTING CHECKLIST
Before BuiltByBit launch:
- Clean install on test VPS (not Firefrost nodes)
- Database variables created correctly
- CurseForge detection works (manifest.json)
- Modrinth detection works (modrinth.index.json)
- FTB detection works (instance.json)
- API timeout handling (no crashes)
- Clean uninstall (restores UI, removes DB vars)
- Force re-scan button functional
- Manual override in Startup tab works
- API key admin panel functional
- Status badges display correctly (green/red/yellow)
- Beta testing complete (3-5 users, 1 week)
11. COMPLETION CRITERIA
This implementation is COMPLETE when:
✅ All code blocks assembled into working extension
✅ All test cases pass
✅ Beta testing validated
✅ BuiltByBit listing published
✅ Demo video recorded
✅ Documentation complete
✅ Support Discord created
✅ First sale received
Fire + Frost + Foundation = Where Code Becomes Commerce 💙🔥❄️💰
Implementation guide created: February 22, 2026
Created by: The Chronicler #21
Total code blocks: 20+ organized components
Ready for: Assembly and testing