Dorian e8a0e1af19 feat: add Ollama proxy timeouts, SSH key migration, polish skills, and demo content
- Update all skill SSH commands from sshpass to key-based auth (~/.ssh/archipelago-deploy)
- Add proxy_connect_timeout 120s to nginx Ollama location blocks
- Add new polish/sweep skills for overnight automation
- Add demo content (documents, photos) for demo stack
- Add .ssh/ to .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 08:06:52 +00:00

2.5 KiB

Skill: Polish Loading States

Add skeleton loaders, loading indicators, timeout warnings, and empty states to all async views. No view should ever show a blank screen.

Skeleton Loader Component

Create or use a SkeletonLoader.vue component with the glassmorphism style:

  • Background: bg-white/5 with shimmer animation
  • Rounded corners matching the card it replaces
  • Animate with CSS @keyframes shimmer (translate gradient left to right)
  • Must use global classes from style.css, not inline Tailwind

Views to Fix

For EACH view in neode-ui/src/views/, verify these states exist:

1. Loading State

  • Show skeleton placeholders immediately on mount
  • Pattern:
    <template>
      <div v-if="isLoading">
        <!-- Skeleton matching the layout -->
      </div>
      <div v-else>
        <!-- Real content -->
      </div>
    </template>
    

2. Empty State

  • When data loads but is empty (zero items)
  • Show helpful message with CTA
  • Pattern:
    <div v-if="!isLoading && items.length === 0" class="glass-card text-center py-12">
      <p class="text-white/60">No apps installed yet</p>
      <router-link to="/marketplace" class="glass-button mt-4">Browse Marketplace</router-link>
    </div>
    

3. Timeout Warning

  • After 15 seconds of loading, show "Taking longer than expected..."
  • After 30 seconds, show troubleshooting options
  • Pattern:
    const loadingTooLong = ref(false)
    let timeout: ReturnType<typeof setTimeout>
    
    onMounted(() => {
      timeout = setTimeout(() => { loadingTooLong.value = true }, 15000)
    })
    
    watch(isLoading, (val) => { if (!val) clearTimeout(timeout) })
    

Priority Views (must have all 3 states)

  1. Apps.vue — app grid skeleton, "No apps installed" empty state
  2. AppDetails.vue — detail card skeleton, loading indicator
  3. Marketplace.vue — app card grid skeleton, "Loading apps..." with timeout
  4. Dashboard.vue — metric card skeletons
  5. Cloud.vue — file list skeleton, "No files" empty state
  6. Settings.vue — settings section skeleton
  7. Server.vue — server info skeleton

Verification

For each view, confirm:

  • isLoading ref exists and is set properly
  • Template has v-if="isLoading" skeleton section
  • Template has empty state for zero-data case
  • Loading timeout warning after 15s
  • Skeleton uses global classes, not inline Tailwind

Deploy After Fixes

Always deploy and verify on live server:

./scripts/deploy-to-target.sh --live

Test by throttling network in browser DevTools to observe loading states.