diff --git a/dashboard/src/routes/+page.svelte b/dashboard/src/routes/+page.svelte
index 45a2cb6c..10c6d319 100644
--- a/dashboard/src/routes/+page.svelte
+++ b/dashboard/src/routes/+page.svelte
@@ -295,8 +295,8 @@
0;
const memGB = Math.round(totalMem / (1024 * 1024 * 1024));
const name = firstNode.friendly_name || "Your Mac";
- const deviceType = (firstNode.device_type || "macbook pro").toLowerCase();
- return { name, memoryGB: memGB || 36, deviceType };
+ const modelId = (firstNode.system_info?.model_id || "macbook pro").toLowerCase();
+ return { name, memoryGB: memGB || 36, deviceType: modelId };
});
let showContinueButton = $state(false);
@@ -532,7 +532,7 @@
connectionIsRed.set(0);
}, 3700);
const t7 = setTimeout(() => {
- modelBlockY.set(115); // Settle back down just above the device
+ modelBlockY.set(125); // Settle back down just above the device
}, 4800);
const t8 = setTimeout(() => {
advanceStep(6);
@@ -552,13 +552,39 @@
}
});
- // Recommended models for onboarding (biggest to smallest that fit, limited to 6)
+ // Recommended models for onboarding: 2 large, 2 medium, 2 small
+ // Always includes Llama-3.2-3B-4bit as a fast-loading small option
+ const PINNED_ONBOARDING_MODEL = "mlx-community/Llama-3.2-3B-Instruct-4bit";
const onboardingModels = $derived.by(() => {
if (models.length === 0) return [];
- return [...models]
+ const sorted = [...models]
.filter((m) => hasEnoughMemory(m) && getModelSizeGB(m) > 0)
- .sort((a, b) => getModelSizeGB(b) - getModelSizeGB(a))
- .slice(0, 6);
+ .sort((a, b) => getModelSizeGB(b) - getModelSizeGB(a));
+ if (sorted.length <= 6) return sorted;
+
+ // Split into thirds by size: large (top third), medium (middle), small (bottom)
+ const third = Math.max(1, Math.floor(sorted.length / 3));
+ const large = sorted.slice(0, third);
+ const medium = sorted.slice(third, third * 2);
+ const small = sorted.slice(third * 2);
+
+ // Pick 2 from each tier, ensuring pinned model counts as a small pick
+ const pinned = small.find((m) => m.id === PINNED_ONBOARDING_MODEL)
+ || sorted.find((m) => m.id === PINNED_ONBOARDING_MODEL);
+ const pickLarge = large.slice(0, 2);
+ const pickMedium = medium.slice(0, 2);
+ const pickSmall = pinned
+ ? [small.find((m) => m.id !== PINNED_ONBOARDING_MODEL) || small[0], pinned].filter(Boolean)
+ : small.slice(0, 2);
+
+ const result = [...pickLarge, ...pickMedium, ...pickSmall];
+ // Deduplicate (in case pinned was already picked)
+ const seen = new Set
{Math.max(1, nodeCount)} {Math.max(1, nodeCount) === 1 ? 'Device' : 'Devices'} in your EXO network
+ + {#if onboardingStep === 1} + +