A prerendered marketing website for Appsome! (software & hardware development studio), built on the Appsome! Blueprint design system. This package is a SvelteKit scaffold wired to the design tokens, ready for your team (or Claude Code) to flesh out and ship.
It replaces the earlier React preview that lived in ui_kits/marketing-site/
(now removed). The visual language, copy and layout are identical — only the
framework changed.
The .svelte/.ts/.css files here are real, working source — not throwaway
HTML mocks. The site is built out: the token bridge, configs, chrome (Nav /
Footer), the committed centered hero, the one-pager home (Services · Work
preview · Process · Contact), the All Work list (/work), two project
detail templates (Case Study + App Landing) behind one [slug] route, a
"trusted by" customer strip, and the standalone contact route are all implemented.
Recreate everything in your environment's conventions; review before shipping.
src/lib/components/ui/is the design system's component library, copied in 1:1. All 12 primitives (Button, IconButton, Tag, Badge, Avatar, StatBlock, Input, Toggle, Card, BlueprintFrame, Callout, Tabs) are the exact same.sveltefiles that live in the design-system project — a single source of truth. They're self-contained Svelte 5 components styled with scoped<style>blocks that read the design tokens (CSS custom properties); they pull in no Tailwind utilities and no npm deps, so they drop into any Svelte project and stay in sync if you re-copy them. Keep them in sync by re-copying from the design system rather than editing here.
High-fidelity. Exact colors, type, spacing and interactions come from the design-system tokens. Build pixel-faithfully; don't re-interpret the look.
| Concern | Choice |
|---|---|
| Framework | SvelteKit (Svelte 5 runes: $props, $state, $derived) |
| Styling | Tailwind v4 (CSS-first, @theme in src/app.css — no tailwind.config.js) |
| Tokens → Tailwind | Mapped into the theme, backed by the system's CSS vars (bg-accent, text-brand, border-navy-700, font-display, rounded-md all work) |
| Components | Design-system Svelte 5 primitives (ui/, copied 1:1 from the DS — scoped styles + CSS vars, no Tailwind/npm deps). shadcn-svelte (bits-ui + tailwind-variants) optional for any extra primitives you need |
| Adapter | adapter-static — whole site prerendered to HTML |
| Icons | @lucide/svelte (matches the system's Lucide choice) |
appsome-marketing-site/
├─ package.json # deps (SvelteKit, Tailwind v4, bits-ui, lucide)
├─ svelte.config.js # adapter-static + $lib alias (code in §Config files)
├─ vite.config.ts # @tailwindcss/vite + sveltekit (code in §Config files)
├─ tsconfig.json
├─ static/
│ ├─ appsome-logo-white.png # brand wordmark (copied from the DS)
│ └─ favicon.png
└─ src/
├─ app.html # html shell (class="dark", navy bg)
├─ app.css # ★ Tailwind v4 entry + @theme token bridge
├─ lib/
│ ├─ utils.ts # cn() — clsx + tailwind-merge
│ ├─ styles/
│ │ ├─ tokens.css # @imports the token files below
│ │ └─ tokens/ # colors / typography / spacing / effects / fonts / base
│ │ └─ … # ← copied verbatim from the design system
│ └─ components/
│ ├─ Nav.svelte # sticky blur nav + mobile menu (one-pager anchors + /work)
│ ├─ Footer.svelte
│ ├─ Hero.svelte # 3 variants; home uses CENTERED (committed)
│ ├─ SectionHead.svelte # eyebrow + title + sub
│ ├─ CustomerLogos.svelte# ★ "trusted by" strip (placeholder wordmarks)
│ ├─ sections/ # ★ one-pager home sections
│ │ ├─ Services.svelte ├─ WorkPreview.svelte (featured + "See all work →")
│ │ ├─ Process.svelte └─ ContactBlock.svelte (slim: email + message)
│ ├─ work/ # ★ work surfaces
│ │ ├─ WorkTile.svelte # card tile (home preview)
│ │ ├─ WorkRow.svelte # full-width list row (/work)
│ │ ├─ CaseStudyDetail.svelte
│ │ ├─ AppLandingDetail.svelte
│ │ ├─ StoreBadge.svelte # App Store / Google Play / Mac App Store / Setapp
│ │ ├─ PhoneFrame.svelte # CSS phone bezel + slot
│ │ ├─ DesktopFrame.svelte # CSS window chrome + slot
│ │ └─ ScreenshotSlot.svelte # drop-in image slot / placeholder
│ └─ ui/ # ★ design-system primitives, copied 1:1 (single source)
│ ├─ Button.svelte ├─ IconButton.svelte
│ ├─ Tag.svelte ├─ Badge.svelte
│ ├─ Avatar.svelte ├─ StatBlock.svelte
│ ├─ Input.svelte ├─ Toggle.svelte
│ ├─ Card.svelte ├─ BlueprintFrame.svelte
│ ├─ Callout.svelte └─ Tabs.svelte
├─ lib/data/projects.ts # ★ project content + types (case-study | app)
└─ routes/
├─ +layout.svelte # imports app.css, wraps Nav/main/Footer
├─ +layout.ts # prerender = true
├─ +page.svelte # ★ Home one-pager (centered hero + sections)
├─ work/+page.svelte # ★ All Work — full-width row list
├─ projects/[slug]/
│ ├─ +page.ts # entries() → prerendered slugs
│ └─ +page.svelte # ★ router: branches on project.type
└─ contact/+page.svelte # standalone full contact form (NDA toggle)
src/lib/styles/tokens/ is copied verbatim from the design system — it's the
single source of truth (:root { --navy-900, --accent, --brand, --space-*, … },
the @font-face/webfont @import, and the .bp-grid / .bp-grid-major /
.bp-dots / .bp-ticks helper classes).
src/app.css then:
@import 'tailwindcss';@import '$lib/styles/tokens.css';(the raw vars + helpers)- Re-exposes a curated subset as Tailwind theme tokens referencing the vars:
→ utilities like
@theme { --color-accent: var(--accent); --color-brand: var(--brand); --color-navy-900: var(--navy-900); --font-display: 'Space Grotesk', sans-serif; --radius-md: 8px; /* …see app.css for the full map */ }
bg-accent,text-ink-secondary,border-navy-700,font-mono,rounded-lgare generated, and because they point at the CSS vars, editing a token in the design system flows straight through.
Text colors are exposed as ink / ink-secondary / ink-muted / ink-faint /
annotation (so text-ink-muted etc.). shadcn-svelte's expected vars
(--background, --primary, --ring, …) are aliased to brand tokens in an
@layer base block so generated components inherit the look.
⚠️ Fonts load from the Google Fonts CDN viatokens/fonts.css. To self-host, drop woff2 files instatic/fonts/and swap the@importfor@font-facerules.
npm create svelte@latest appsome-marketing-site # Skeleton, TypeScript
cd appsome-marketing-site
npm i -D tailwindcss @tailwindcss/vite @sveltejs/adapter-static
npm i @lucide/svelte bits-ui tailwind-variants clsx tailwind-merge
npx shadcn-svelte@latest init # choose CSS vars; point at src/app.css
# then drop in the files from this handoff (configs, app.css, lib/, routes/, static/)
npm run devAdd shadcn components only if you need primitives beyond the 12 in ui/:
npx shadcn-svelte@latest add <name>, then restyle with the mapped utilities
(bg-brand, border-border-strong, …). The ui/ primitives are the design
system's own components (scoped styles + CSS vars) — prefer them, and keep them in
sync by re-copying from the design system rather than editing in place.
These two build configs import npm packages, so they're listed here rather than as live files in the bundle (the design-system project they sit in would try to bundle them). Create them at the project root verbatim:
svelte.config.js
import adapter from '@sveltejs/adapter-static';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: vitePreprocess(),
kit: {
adapter: adapter({ pages: 'build', assets: 'build', fallback: undefined, strict: true }),
alias: { $lib: 'src/lib' }
}
};
export default config;vite.config.ts
import { sveltekit } from '@sveltejs/kit/vite';
import tailwindcss from '@tailwindcss/vite';
import { defineConfig } from 'vite';
// Tailwind v4 runs as a Vite plugin — no tailwind.config.js. Theme lives in src/app.css.
export default defineConfig({
plugins: [tailwindcss(), sveltekit()]
});
src/lib/utils.tsships a dependency-freecn()so the scaffold compiles cleanly; swap it for theclsx+tailwind-mergeversion (both already inpackage.json) in production — the swap is documented inline in that file.
Per your direction, Services / Work / Process / Contact are collapsed onto the
home page, each with an anchor id (#services, #work, #process, #contact)
the nav links scroll to (scroll-mt-24 offsets the sticky nav). Order:
Hero → Customer strip → Services → Work preview → Process → Contact.
- Hero — committed to CENTERED (
Hero variant="centered"). Centered statement “We draft it. / We dimension it. / We build it to spec.” over a full-bleed.bp-grid-majorwith a radial vignette; CTAs scroll to#contact/#services; 3StatBlocks. (Hero.sveltestill contains thesplit&panelvariants for reference — delete them once you're sure.) - Customer strip —
CustomerLogos.svelte, a quiet “trusted by” band right under the hero. No customer logo files were supplied, so it renders neutral wordmark placeholders (NORTHWIND,VECTORA, …) at low opacity. Replace each with a real logo: drop PNG/SVGs instatic/customers/and swap the<span>for<img src="/customers/acme.svg" …>. No links, per spec. - Services —
sections/Services.svelte. 4-up grid ofCard(eyebrow01 · ENGINEERING…, icon, body, mono footer);interactivegives the cyan hairline + lift. - Work preview —
sections/WorkPreview.svelte. Section head + “See all work →” (→/work); the featured projects (featuredProjectsfrom the data file) asWorkTiles. App-type projects get a small “App” marker. - Process —
sections/Process.svelte,id="process",.bp-gridband. 4 steps with a monoSTEP 0Nkicker + connecting arrow on desktop. - Contact —
sections/ContactBlock.svelte,id="contact". **Slimmed to email- message** per spec: copy +
mailto:on the left, a two-field form (email, message) on the right with aCalloutsuccess state and a “Need an NDA or more detail? →” link to the full/contactroute.
- message** per spec: copy +
The “all work” list you asked for. Page hero + a full-width row list
(WorkRow): each row = index + sector·year, title (with an “App” marker for app
projects) + summary + tags, and a status Badge + arrow on the right. Hover lifts
the row tint + accents the title/arrow. Rows link to /projects/[slug]. Driven by
the full projects array.
A thin router: looks up the project by slug and branches on project.type,
rendering one of two templates. Unknown slugs show a small 404 block; prerendered
slugs are listed in +page.ts entries() (keep in sync with the data file).
- Case Study —
work/CaseStudyDetail.svelte. Back link, sector eyebrow, title, intro, tags → 4-upStatBlockstrip → two-column brief/“what we built” + aBlueprintFramespec aside → “Start a build like this” CTA. - App Landing —
work/AppLandingDetail.svelte, for mobile/desktop apps. Hero (copy + tagline + store badges + platforms meta, with 1–2PhoneFrames fanned beside it) → Screens gallery ofPhoneFrames → optional Desktop section (DesktopFrame, shown only ifdesktopShotis set) → 3 highlight cards → CTA repeating the store badges.- Store badges (
StoreBadge.svelte) support App Store, Google Play, Mac App Store, Setapp — rendered as Appsome-styled CTA buttons (icon + kicker + name), not reproductions of the official badge artwork; restyle/replace with official badges at your discretion. - Screenshots are drop-in slots (
ScreenshotSlot.svelte): eachShotin the data shows a labelled placeholder with the recommended export size until you set itssrcto a/staticpath. Phone frames are CSS bezels (1290×2796 ratio); desktop frame is a CSS window at 16:10 — swap for real device art if you prefer.
- Store badges (
The fuller enquiry form (name, email, company, message, NDA toggle), linked from
the home contact block’s “Need an NDA or more detail?”. Bordered form card using
Input / Toggle / Button with a Callout success state, plus a details aside.
Replace the fake submit with a SvelteKit form action or API call.
One typed projects array feeds the home preview, /work, and the detail router.
Each project declares type: 'case-study' | 'app', featured, status, tags, and
template-specific fields (stats/brief/spec for case studies;
tagline/stores/phoneShots/desktopShot/highlights for apps). Move this to a
CMS/markdown + a load function for production; the shape stays the same.
- Nav: sticky,
bg-navy-950/70+backdrop-blur-md, hairline bottom border; links highlighttext-accenton the active route; collapses to a burger menu belowmd(toggled with$state). - Buttons: hover brightens one step (
brand → brand-hover,accent → accent-bright); pressactive:scale-[0.98]; 150ms color transitions. - Cards/tiles: hover → cyan hairline (
border-accent) +-translate-y-[3px]shadow-lg, 200ms.
- Inputs: focus →
border-accent+ cyan glow shadow. - Hero switcher: dev aid only — remove before launch.
- Motion: fades + ≤8px translate; easings
--ease-out/--ease-snapfrom the tokens; honorprefers-reduced-motion; no infinite loops. - Responsive: nav burger ≤
md; grids reflow (4→2→1) atmd/sm.
Local component state only (Svelte 5 $state) — nav open, hero variant,
contact sent/nda. No global store needed. Project content should move to a
load function (CMS/markdown) rather than the inline placeholder map.
Full set in src/lib/styles/tokens/. Key values:
- Ground
--bg #060c18, surface--surface #0a1322, raised#0d1b30, panel#102338. - Brand
#0276bd(hover#1f8ed4). Accent cyan#36c5f0(bright#5fd4f5). - Text
#eef4fb/#7ba2c8/#4d7fac; annotation#8fe2f9. - Status success
#43d98a, warning#f5a623, danger#f7615f. - Type Space Grotesk (display) · IBM Plex Sans (body) · IBM Plex Mono (labels,
UPPERCASE,
tracking 0.14em). - Radii 3/5/8/12/18px. Shadows ink-tinted
rgba(2,8,20,…). - Spacing 4px module; container 1200px; blueprint grid unit 24px / major 120px.
static/appsome-logo-white.png— wordmark (white, transparent). Navy/cyan variants + favicons live in the design system'sassets/.static/favicon.png— theA!avatar.- Icons:
@lucide/svelte.
Everything under handoff/sveltekit-marketing-site/. Start at src/app.css
(token bridge), then Hero.svelte, then the routes.
Engineering-confident: precise, understated, “we”/“you”, sentence case for prose, UPPERCASE mono for labels/specs, no emoji. Lean on real numbers/specs only.