feat(deck): rework slides + registry for the 4-entity model

Title lists the three experiences on the Archipelago network; Tech slide
reframed as "Archipelago · the shared backbone"; new SolLunar (city) and
Festivals deep-dives replace the old Archipelago/Solunar slides;
EntitiesSlide shows 3 experience cards + an Archipelago backbone banner;
EntityDetail shows the festival's example (Solar Punk Summit); cost slides
use the pine/indigo/rose/clay accents. Deck reordered accordingly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-07-31 18:07:43 +02:00
commit 0353665fb3
9 changed files with 57 additions and 27 deletions

View file

@ -9,8 +9,8 @@ import VisionSlide from './slides/VisionSlide.vue'
import NetworkSlide from './slides/NetworkSlide.vue' import NetworkSlide from './slides/NetworkSlide.vue'
import TechSlide from './slides/TechSlide.vue' import TechSlide from './slides/TechSlide.vue'
import EntitiesSlide from './slides/EntitiesSlide.vue' import EntitiesSlide from './slides/EntitiesSlide.vue'
import ArchipelagoSlide from './slides/ArchipelagoSlide.vue' import SolLunarSlide from './slides/SolLunarSlide.vue'
import SolunarSlide from './slides/SolunarSlide.vue' import FestivalsSlide from './slides/FestivalsSlide.vue'
import ChateauSlide from './slides/ChateauSlide.vue' import ChateauSlide from './slides/ChateauSlide.vue'
import GallerySlide from './slides/GallerySlide.vue' import GallerySlide from './slides/GallerySlide.vue'
import EcosystemSlide from './slides/EcosystemSlide.vue' import EcosystemSlide from './slides/EcosystemSlide.vue'
@ -26,10 +26,10 @@ const slides = [
{ id: 'title', label: 'Title', component: TitleSlide }, { id: 'title', label: 'Title', component: TitleSlide },
{ id: 'vision', label: 'Vision', component: VisionSlide }, { id: 'vision', label: 'Vision', component: VisionSlide },
{ id: 'network', label: 'The network', component: NetworkSlide }, { id: 'network', label: 'The network', component: NetworkSlide },
{ id: 'tech', label: 'Core stack', component: TechSlide }, { id: 'archipelago', label: 'Archipelago', component: TechSlide },
{ id: 'entities', label: 'Three entities', component: EntitiesSlide }, { id: 'entities', label: 'Three experiences', component: EntitiesSlide },
{ id: 'archipelago', label: 'Archipelago', component: ArchipelagoSlide }, { id: 'sollunar', label: 'SolLunar Punk Society', component: SolLunarSlide },
{ id: 'solunar', label: 'SolLunar Society', component: SolunarSlide }, { id: 'festivals', label: 'Pop-up Festivals', component: FestivalsSlide },
{ id: 'chateau', label: 'Chateau du Faune', component: ChateauSlide }, { id: 'chateau', label: 'Chateau du Faune', component: ChateauSlide },
{ id: 'gallery', label: 'Gallery', component: GallerySlide }, { id: 'gallery', label: 'Gallery', component: GallerySlide },
{ id: 'ecosystem', label: 'One membership', component: EcosystemSlide }, { id: 'ecosystem', label: 'One membership', component: EcosystemSlide },

View file

@ -18,6 +18,7 @@ const a = props.entity.accent
> >
{{ entity.role }} {{ entity.role }}
</span> </span>
<span v-if="entity.example" class="text-sm text-sand-dim">e.g. {{ entity.example }}</span>
<PlaceholderBadge label="name" /> <PlaceholderBadge label="name" />
</div> </div>
<p class="mt-4 max-w-2xl text-lg text-sand-dim">{{ entity.blurb }}</p> <p class="mt-4 max-w-2xl text-lg text-sand-dim">{{ entity.blurb }}</p>
@ -68,7 +69,7 @@ const a = props.entity.accent
</div> </div>
<div class="flex items-center gap-2 rounded-2xl border border-white/10 bg-white/[0.03] px-4 py-3 text-xs text-sand-dim"> <div class="flex items-center gap-2 rounded-2xl border border-white/10 bg-white/[0.03] px-4 py-3 text-xs text-sand-dim">
<Icon name="Layers" class="size-4 text-amber-300" /> <Icon name="Layers" class="size-4 text-amber-300" />
Runs the full core stack same membership, kiosk &amp; app as every node. Runs on Archipelago same membership, kiosk &amp; app as every node.
</div> </div>
</div> </div>
</div> </div>

View file

@ -5,9 +5,9 @@ import PlaceholderBadge from '../components/PlaceholderBadge.vue'
import { costCategories, categoryTotal, fmtUsd } from '../data' import { costCategories, categoryTotal, fmtUsd } from '../data'
const text: Record<string, string> = { const text: Record<string, string> = {
amber: 'text-amber-300',
pine: 'text-pine-300', pine: 'text-pine-300',
indigo: 'text-indigo-300', indigo: 'text-indigo-300',
rose: 'text-rose-300',
clay: 'text-clay-400', clay: 'text-clay-400',
} }
</script> </script>

View file

@ -1,18 +1,20 @@
<script setup lang="ts"> <script setup lang="ts">
import SlideFrame from '../components/SlideFrame.vue' import SlideFrame from '../components/SlideFrame.vue'
import Icon from '../components/Icon.vue' import Icon from '../components/Icon.vue'
import { entities, accentText, accentRing } from '../data' import { surfaceEntities, entityById, accentText, accentRing } from '../data'
const archipelago = entityById('archipelago')
</script> </script>
<template> <template>
<SlideFrame <SlideFrame
kicker="The collaboration" kicker="The collaboration"
title="Three entities, one network" title="Three experiences, one backbone"
subtitle="Deliberately different — a city hub, a travelling festival, a farm — each with its own character, all running the identical core stack." subtitle="Deliberately different — a city hub, a travelling festival, a farm — each with its own character, all running on Archipelago."
> >
<div class="grid gap-5 md:grid-cols-3"> <div class="grid gap-5 md:grid-cols-3">
<div <div
v-for="e in entities" v-for="e in surfaceEntities"
:key="e.id" :key="e.id"
class="flex flex-col rounded-2xl border p-6" class="flex flex-col rounded-2xl border p-6"
:class="accentRing[e.accent]" :class="accentRing[e.accent]"
@ -22,7 +24,7 @@ import { entities, accentText, accentRing } from '../data'
<Icon :name="e.icon" class="size-6" /> <Icon :name="e.icon" class="size-6" />
</span> </span>
<div> <div>
<h3 class="font-display text-xl font-semibold text-sand">{{ e.name }}</h3> <h3 class="font-display text-lg font-semibold leading-tight text-sand">{{ e.name }}</h3>
<p class="text-xs uppercase tracking-wider" :class="accentText[e.accent]">{{ e.role }}</p> <p class="text-xs uppercase tracking-wider" :class="accentText[e.accent]">{{ e.role }}</p>
</div> </div>
</div> </div>
@ -31,14 +33,25 @@ import { entities, accentText, accentRing } from '../data'
<div class="mt-5 flex items-center gap-2 border-t border-white/10 pt-4 text-xs text-sand-dim"> <div class="mt-5 flex items-center gap-2 border-t border-white/10 pt-4 text-xs text-sand-dim">
<Icon name="Layers" class="size-4 text-amber-300" /> <Icon name="Layers" class="size-4 text-amber-300" />
Full core stack &amp; membership Full membership &amp; ecosystem
</div> </div>
</div> </div>
</div> </div>
<p class="mt-6 text-center text-sm text-sand-dim"> <!-- the shared backbone beneath all three -->
Same card, same kiosk, same app the <div class="mt-5 flex items-center gap-4 rounded-2xl border p-5" :class="accentRing[archipelago.accent]">
<span class="text-sand">full experience regardless of location.</span> <span class="grid size-11 shrink-0 place-items-center rounded-xl bg-white/5" :class="accentText[archipelago.accent]">
</p> <Icon :name="archipelago.icon" class="size-6" />
</span>
<div class="min-w-0 flex-1">
<h3 class="font-display text-lg font-semibold text-sand">
{{ archipelago.name }}
<span class="ml-1 text-xs font-normal uppercase tracking-wider" :class="accentText[archipelago.accent]">
· {{ archipelago.role }}
</span>
</h3>
<p class="text-sm text-sand-dim">{{ archipelago.blurb }}</p>
</div>
</div>
</SlideFrame> </SlideFrame>
</template> </template>

View file

@ -0,0 +1,8 @@
<script setup lang="ts">
import EntityDetail from '../components/EntityDetail.vue'
import { entityById } from '../data'
</script>
<template>
<EntityDetail :entity="entityById('festivals')" />
</template>

View file

@ -7,21 +7,21 @@ import { costCategories, categoryTotal, raiseTotal, fmtUsd } from '../data'
// per-category colour (includes the shared 'amber' core-stack category) // per-category colour (includes the shared 'amber' core-stack category)
const barBg: Record<string, string> = { const barBg: Record<string, string> = {
amber: 'bg-amber-400',
pine: 'bg-pine-500', pine: 'bg-pine-500',
indigo: 'bg-indigo-500', indigo: 'bg-indigo-500',
rose: 'bg-rose-500',
clay: 'bg-clay-400', clay: 'bg-clay-400',
} }
const text: Record<string, string> = { const text: Record<string, string> = {
amber: 'text-amber-300',
pine: 'text-pine-300', pine: 'text-pine-300',
indigo: 'text-indigo-300', indigo: 'text-indigo-300',
rose: 'text-rose-300',
clay: 'text-clay-400', clay: 'text-clay-400',
} }
const ring: Record<string, string> = { const ring: Record<string, string> = {
amber: 'border-amber-400/50 bg-amber-400/[0.06]',
pine: 'border-pine-500/50 bg-pine-500/[0.06]', pine: 'border-pine-500/50 bg-pine-500/[0.06]',
indigo: 'border-indigo-500/50 bg-indigo-500/[0.06]', indigo: 'border-indigo-500/50 bg-indigo-500/[0.06]',
rose: 'border-rose-500/50 bg-rose-500/[0.06]',
clay: 'border-clay-400/50 bg-clay-400/[0.06]', clay: 'border-clay-400/50 bg-clay-400/[0.06]',
} }

View file

@ -0,0 +1,8 @@
<script setup lang="ts">
import EntityDetail from '../components/EntityDetail.vue'
import { entityById } from '../data'
</script>
<template>
<EntityDetail :entity="entityById('sollunar')" />
</template>

View file

@ -6,9 +6,9 @@ import { tech } from '../data'
<template> <template>
<SlideFrame <SlideFrame
kicker="The technology" kicker="Archipelago · the shared backbone"
title="Open hardware, sovereign software" title="Open hardware, sovereign software"
subtitle="The stack under every node — owned by the network, documented to be rebuilt anywhere." subtitle="Archipelago is the stack under every entity — owned by the network, documented to be rebuilt anywhere. Build it once; every place plugs in."
> >
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3"> <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
<div <div

View file

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import SlideFrame from '../components/SlideFrame.vue' import SlideFrame from '../components/SlideFrame.vue'
import PlaceholderBadge from '../components/PlaceholderBadge.vue' import PlaceholderBadge from '../components/PlaceholderBadge.vue'
import { brand, entities, accentText } from '../data' import { brand, surfaceEntities, accentText } from '../data'
</script> </script>
<template> <template>
@ -22,12 +22,12 @@ import { brand, entities, accentText } from '../data'
<!-- the three collaborating entities --> <!-- the three collaborating entities -->
<div class="mt-10 flex flex-wrap items-center justify-center gap-x-3 gap-y-2 text-sm text-sand-dim"> <div class="mt-10 flex flex-wrap items-center justify-center gap-x-3 gap-y-2 text-sm text-sand-dim">
<span class="uppercase tracking-[0.2em]">A collaboration between</span> <span class="uppercase tracking-[0.2em]">Three experiences, one backbone</span>
</div> </div>
<div class="mt-3 flex flex-wrap items-center justify-center gap-3"> <div class="mt-3 flex flex-wrap items-center justify-center gap-3">
<template v-for="(e, i) in entities" :key="e.id"> <template v-for="(e, i) in surfaceEntities" :key="e.id">
<span class="font-display text-lg font-semibold" :class="accentText[e.accent]">{{ e.name }}</span> <span class="font-display text-lg font-semibold" :class="accentText[e.accent]">{{ e.name }}</span>
<span v-if="i < entities.length - 1" class="text-sand-dim">·</span> <span v-if="i < surfaceEntities.length - 1" class="text-sand-dim">·</span>
</template> </template>
</div> </div>