Introduces App\Support\DashboardSchedule (modelled on LHITS_Dashboard's pattern) as a single settings-driven registry for recurring Artisan jobs, replacing the two hard-coded Schedule::command() lines in routes/console.php. Migrated unchanged: - integrations_refresh (integrations:refresh), every_30_seconds, withoutOverlapping(5) - alerts_scan (alerts:scan), every_30_seconds, withoutOverlapping(5) New: - etsy_sync (etsy:sync), every_15_minutes - forces a fresh pull of Etsy receipts/listings into the existing IntegrationCache entries, decoupled from the bundled integrations:refresh job so it can be tuned/disabled independently of Parcel2Go/BamBuddy/dryer refreshes. - etsy_token_refresh (etsy:refresh-token), every_45_minutes - proactively refreshes the Etsy OAuth token (tokens last ~1hr) via a new public Etsy::refreshAccessToken() wrapper around the existing on-demand accessToken() refresh logic, so the connection survives quiet periods. Frequency is persisted to storage/app/dashboard-schedules.json (no app_settings table exists in this app, unlike LHITS's AppSetting-backed store) and surfaced in a new 'Scheduler' section on the existing Settings page (ScheduleSettingsController + routes), with per-job frequency dropdowns and manual 'Run now' buttons, matching the page's existing Tailwind conventions. Tests: SchedulerTest (registry/frequency behavior), ScheduleSettingsTest (settings UI + authorization), EtsySyncScheduledJobsTest (new commands, Http::fake only, no live Etsy calls).
HickLab3D dashboard
Laravel 13, Tailwind CSS 4, and MySQL dashboard for the HickLab3D workshop. It includes user accounts, Etsy shop data, BamBuddy printer status, Parcel2Go orders, and filament dryer control.
Setup
Requirements: PHP 8.3+, Composer, Node.js, and MySQL. Point the web server document root at public/.
composer install
npm install
cp .env.example .env
php artisan key:generate
On Windows PowerShell, use Copy-Item .env.example .env in place of cp .env.example .env.
Set DB_* in .env to your MySQL database, then run:
php artisan migrate
php artisan app:create-admin your-username you@example.com
npm run build
php artisan serve
The admin command prompts for a password. Never pass it on the command line. For local front-end development, use npm run dev alongside php artisan serve.
The migrations use the legacy table and column names. If you point the app at the existing HickLab3D database, back it up first. The migrations skip tables already present and create Laravel's session, cache, and job tables. Existing schema variations have not been verified against a database dump. Do not run migrate:fresh on a database with production data.
Integrations
- Enter Etsy, Parcel2Go, BamBuddy, and dryer connection details on the admin Settings page. Saved values are encrypted in the database and take precedence over matching
.envvalues. - Existing
P2G_*,BAMBUDDY_*,DRYER_*, andETSY_*environment values remain available as fallbacks. Save each integration on the Settings page to import those values into the database. - Connect the Etsy shop with OAuth after saving its app credentials. The browser talks to authenticated Laravel routes for dryer status and controls.
- Runtime Etsy credentials remain Settings-page rows /
ETSY_*env (optional aliases:HL3D_ETSY_KEYSTRING,HL3D_ETSY_SECRET). Never put tokens in MCP config.
Etsy MCP
First-party stdio MCP for HL3D agents. It uses the stored HickLab3D shop connection — agents must not start a new OAuth dance.
php artisan etsy:mcp
Register it from this repo's .mcp.json as server name etsy (php + artisan etsy:mcp). Example for an HL3D Hermes profile after this server exists:
hermes -p hl3d_teamlead mcp add etsy --command php --args artisan etsy:mcp
Run the command from the dashboard app root so it inherits .env. After deploy, an admin must reconnect Etsy in the dashboard so the token includes listings_r listings_w transactions_r transactions_w shops_r. New listings are created as drafts; publishing requires etsy_publish_listing with confirm=true.
Etsy Open API v3 has no conversation inbox (conversations_* scopes do not exist). Receipt notes are exposed; sending a buyer-inbox reply is not.
Verification
php artisan test --compact
npm run build
The test suite uses an in-memory SQLite database. MySQL and the external services need environment-specific smoke checks with your credentials and devices.