Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Solder Laravel Package

technicpack/solder

TechnicPack Solder is a Laravel-based repository and API for Minecraft modpacks, helping you manage packs, builds, and launcher downloads from a web admin interface and serve them to Technic Platform clients.

View on GitHub
Deep Wiki
Context7

Getting Started

This is an application, not a library. technicpack/solder is the Technic Solder server itself — a full Laravel app (PHP 8.4 / Laravel 13 / Fortify / Sanctum) that serves modpack metadata to the Technic Launcher. The 0 dependents and the repo layout confirm it: you do not composer require it into an existing project. You clone/fork the repo, deploy it as its own service, and integrate over its HTTP API. Budget for that operational cost before adopting it.

Minimal path to a working instance:

  1. git clone the repo and start the dev stack: docker compose -f compose.dev.yml up -d (PostgreSQL, mounted .env).
  2. Copy .env.example → .env, set APP_URL, APP_KEY (php artisan key:generate), DB creds, and the mirror settings.
  3. php artisan migrate --seed, then log into /admin with the seeded admin account (check database/seeders/ for the credential; create additional users via the bundled artisan command rather than INSERTing rows).
  4. npm ci && npm run build — the admin panel is Tailwind v4 + Alpine and will throw a Vite manifest exception until built.

Where to look first, in order:

  • routes/api.php — the entire contract with the launcher lives here; it is small enough to read in one sitting.
  • docs/api/ — per-endpoint request/response documentation (including read/root.md, which carries the version string).
  • app/Models/ — Modpack → Build → Modversion → Mod is the whole domain model.
  • .env.example and config/ — mirror disk, rate limiting, cache, auth drivers.
  • agents/rules/ — the repo ships its own conventions (docker, testing, pint, releasing). Follow them; they are accurate and opinionated.

First use case: create a modpack, add a mod, add a modversion pointing at a file on your mirror (MD5 + filesize required), assemble a build containing that modversion, publish it, then curl {APP_URL}/api/modpack/{slug}/{build} and confirm the launcher-shaped JSON comes back. That end-to-end loop is the fastest way to understand the package.

Implementation Patterns

Treat the content hierarchy as your deploy artifact. A Build is an immutable snapshot: a set of Modversion rows pinned at exact versions. Do not mutate a published build to "fix" a mod; cut a new build version and move the modpack's recommended/latest pointers. Launchers and users cache by build version, so in-place edits produce silent divergence.

Mirror layout is part of the contract. Files are referenced by a relative path plus md5 and filesize. Whether the bytes live on S3 (signed/public URLs) or a plain web mirror, the launcher verifies the hash before installing. After any manual upload, re-run the rehash artisan command (php artisan list | grep solder for the exact name) so the DB hashes match the bytes on disk — this is the single most common reason a build "works in the admin panel but fails in the launcher."

Private distribution uses client API keys. Create a client in /admin, hand the key to the consumer, and it is passed on each request (?k=… in the shipped docs; confirm the accepted parameter/header in the request middleware). The /api/verify/{key} endpoint is the cheap way for a client to validate a key at boot instead of failing mid-download.

Automate the pipeline, don't click it. For a real modpack you'll be importing dozens of mods per release. Write an artisan command that reads your source-of-truth (CurseForge/Modrinth export, git repo of manifests), upserts Mod/Modversion rows idempotently keyed on (mod slug, version), creates the Build, attaches pivots in a transaction, then publishes. Put it behind a queued job with retries; wrap the whole thing in DB::transaction() so a partial import never leaves an unpublished half-build.

Client-side integration pattern. Consumers should poll GET /api/modpack/{slug}/{build} with a concrete build version (or the recommended alias), diff the returned mod list against local state, download only changed files, and verify MD5 locally. Cache the response aggressively keyed on build version — the metadata is immutable per build, so there is no reason to re-fetch it on every launcher start.

Extending the app. Add endpoints in routes/api.php behind the existing auth middleware, return Eloquent API Resources (match the existing JSON envelope exactly — third-party launchers are strict), validate with Form Requests, and authorize with Policies. Keep new controllers next to their siblings in app/Http/Controllers/Api/. Use database-schema before writing a migration and search-docs before reaching for a framework idiom — this repo is on Laravel 13, where plenty of blog-era advice is stale.

Testing. All tests are PHPUnit (convert any Pest you find). Feature tests run against in-memory/stock sqlite via phpunit.xml + .env.testing; never point tests at the Postgres dev container. Use RefreshDatabase and the existing factories, and assert on the exact JSON shape — API stability is the product here. Run a single test with --filter= before the suite.

Release hygiene (if you fork). The repo's releasing rule is load-bearing: bump SOLDER_VERSION in app/Providers/AppServiceProvider.php, update CHANGELOG.md, update the version in docs/api/read/root.md, then tag. Clients read that root endpoint to version-gate themselves.

Gotchas and Tips

  • composer require is the wrong mental model. If you were hoping to embed Solder's logic in an existing Laravel app, expect to vendor the models/routes by hand instead. Forking the app is the supported path, which means you own upgrades forever.
  • Stale cache after direct DB edits. API responses are cached and busted by model observers/events on admin writes. Change a row in tinker or SQL and the API will lie to you. php artisan cache:clear after any out-of-band mutation.
  • Never merge the two Compose files. compose.dev.yml (PostgreSQL) and compose.yml (MariaDB) are independent. Merging pulls MariaDB and the production env-injection block into dev — the pgsql driver then hits MariaDB, two databases run at once, and test isolation breaks. Also never run bare docker compose up.
  • DB drift is a real trap. Dev is PostgreSQL, prod is MariaDB, tests are sqlite. Stick to portable query-builder/Eloquent constructs; raw JSON columns and ILIKE will bite you in one of the three.
  • MD5/filesize mismatches fail silently in the admin but loudly in the launcher. When a user reports "download failed," check the hash first, then the URL join (a trailing or missing slash on the mirror base URL produces a 404 that looks like a hash problem).
  • Publication state has two dimensions — the build's published/hidden flag and the modpack's recommended/latest pointers. Setting one and not the other is a classic "the API returns 200 with an empty build" bug. Read the Build migration for exact column names rather than guessing.
  • API keys in query strings leak into access logs and referrers. If you control both ends, prefer the header form; if not, at minimum scrub k= from your reverse-proxy logs and rotate keys per client.
  • Rate limiting is on by default. Bulk import scripts that hammer the API will get throttled — hit the DB/artisan path for writes and reserve the public API for reads.
  • migrate:fresh in prod equals total data loss (modpacks, builds, keys are all in the DB). Use migrate and take a dump before upgrades.
  • Debugging toolkit: database-query/database-schema over raw SQL, route:list --path=api to confirm the middleware stack, browser-logs for admin-panel JS errors, Debugbar for N+1s on the modpack listing page (it is the slowest screen in the app).
  • Upgrading: read CHANGELOG.md and the API docs diff — the server version, the documented example response, and SOLDER_VERSION are supposed to move together, and a mismatch is your early warning that a client will break.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect