step 002 complete
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
// @ts-check
|
||||
import { defineConfig } from 'astro/config';
|
||||
import sitemap from '@astrojs/sitemap';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({});
|
||||
export default defineConfig({
|
||||
site: 'https://qumo.io',
|
||||
integrations: [sitemap()],
|
||||
vite: {
|
||||
plugins: [tailwindcss()],
|
||||
},
|
||||
});
|
||||
|
||||
3
website/src/components/Footer.astro
Normal file
3
website/src/components/Footer.astro
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
// A later step will implement this component
|
||||
---
|
||||
3
website/src/components/Nav.astro
Normal file
3
website/src/components/Nav.astro
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
// Step 003 will implement this component
|
||||
---
|
||||
8
website/src/content/en.json
Normal file
8
website/src/content/en.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"meta": {
|
||||
"siteName": "Qumo",
|
||||
"defaultTitle": "Qumo — Data & AI for Dutch MKB",
|
||||
"defaultDescription": "Qumo helps Dutch mid-market companies turn data into decisions. From BI dashboards to AI-powered workflows, we make data work for your business.",
|
||||
"defaultOgImage": ""
|
||||
}
|
||||
}
|
||||
9
website/src/content/i18n.ts
Normal file
9
website/src/content/i18n.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import enContent from './en.json';
|
||||
import nlContent from './nl.json';
|
||||
|
||||
type Content = typeof enContent;
|
||||
|
||||
export function getContent(locale: string): Content {
|
||||
if (locale === 'nl') return nlContent as Content;
|
||||
return enContent;
|
||||
}
|
||||
8
website/src/content/nl.json
Normal file
8
website/src/content/nl.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"meta": {
|
||||
"siteName": "Qumo",
|
||||
"defaultTitle": "Qumo — Data & AI voor Nederlands MKB",
|
||||
"defaultDescription": "Qumo helpt Nederlandse middelgrote bedrijven data omzetten in beslissingen. Van BI-dashboards tot AI-gedreven workflows — wij laten data werken voor uw bedrijf.",
|
||||
"defaultOgImage": ""
|
||||
}
|
||||
}
|
||||
80
website/src/layouts/BaseLayout.astro
Normal file
80
website/src/layouts/BaseLayout.astro
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
import '../styles/global.css';
|
||||
import Nav from '../components/Nav.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
|
||||
// Import critical font weights with ?url so preload hrefs match Vite-processed URLs
|
||||
import archiaRegularUrl from '../assets/fonts/archia/archia-regular-webfont.woff2?url';
|
||||
import archiaSemiBoldUrl from '../assets/fonts/archia/archia-semibold-webfont.woff2?url';
|
||||
import archiaBoldUrl from '../assets/fonts/archia/archia-bold-webfont.woff2?url';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
description: string;
|
||||
locale?: string;
|
||||
canonicalUrl: string;
|
||||
alternateUrl: string;
|
||||
ogImage?: string;
|
||||
jsonLd?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
const {
|
||||
title,
|
||||
description,
|
||||
locale = 'en',
|
||||
canonicalUrl,
|
||||
alternateUrl,
|
||||
ogImage,
|
||||
jsonLd,
|
||||
} = Astro.props;
|
||||
|
||||
const enUrl = locale === 'en' ? canonicalUrl : alternateUrl;
|
||||
const nlUrl = locale === 'nl' ? canonicalUrl : alternateUrl;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang={locale}>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{title}</title>
|
||||
|
||||
<!-- Favicons -->
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
|
||||
<!-- Font preloads: Regular, SemiBold, Bold only -->
|
||||
<link rel="preload" href={archiaRegularUrl} as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href={archiaSemiBoldUrl} as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href={archiaBoldUrl} as="font" type="font/woff2" crossorigin />
|
||||
|
||||
<!-- Canonical & hreflang -->
|
||||
<link rel="canonical" href={canonicalUrl} />
|
||||
<link rel="alternate" hreflang="en" href={enUrl} />
|
||||
<link rel="alternate" hreflang="nl" href={nlUrl} />
|
||||
<link rel="alternate" hreflang="x-default" href={enUrl} />
|
||||
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content={canonicalUrl} />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:site_name" content="Qumo" />
|
||||
{ogImage && <meta property="og:image" content={ogImage} />}
|
||||
|
||||
<!-- Twitter card -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content={title} />
|
||||
<meta name="twitter:description" content={description} />
|
||||
{ogImage && <meta name="twitter:image" content={ogImage} />}
|
||||
|
||||
<!-- JSON-LD structured data -->
|
||||
{jsonLd && <script type="application/ld+json" set:html={JSON.stringify(jsonLd)} />}
|
||||
<slot name="jsonld" />
|
||||
</head>
|
||||
<body class="bg-midnight text-snow font-archia">
|
||||
<Nav />
|
||||
<slot />
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,17 +1,93 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
|
||||
const title = 'Qumo — Brand Smoke Test';
|
||||
const description = 'Brand token and font weight smoke test — dev artifact.';
|
||||
---
|
||||
|
||||
---
|
||||
<BaseLayout
|
||||
title={title}
|
||||
description={description}
|
||||
locale="en"
|
||||
canonicalUrl="https://qumo.io/"
|
||||
alternateUrl="https://qumo.io/nl"
|
||||
>
|
||||
<main class="p-8 min-h-screen">
|
||||
<h1 class="text-2xl font-bold uppercase mb-8 tracking-widest">Brand Smoke Test</h1>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>Astro</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Astro</h1>
|
||||
</body>
|
||||
</html>
|
||||
<!-- Color Swatches -->
|
||||
<section class="mb-10">
|
||||
<h2 class="text-sm uppercase tracking-widest mb-4 opacity-50">Brand Colors</h2>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<div class="w-24 h-24 rounded bg-midnight border border-snow/20"></div>
|
||||
<span class="text-xs">Midnight<br/>#102022</span>
|
||||
</div>
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<div class="w-24 h-24 rounded bg-snow"></div>
|
||||
<span class="text-xs text-snow/70">Snow<br/>#F3F3F3</span>
|
||||
</div>
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<div class="w-24 h-24 rounded bg-brand-blue"></div>
|
||||
<span class="text-xs">Brand Blue<br/>#5257E4</span>
|
||||
</div>
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<div class="w-24 h-24 rounded bg-brand-red"></div>
|
||||
<span class="text-xs">Brand Red<br/>#F71E3E</span>
|
||||
</div>
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<div class="w-24 h-24 rounded" style="background: var(--gradient-brand)"></div>
|
||||
<span class="text-xs">Gradient<br/>Blue → Red</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Font Weight Samples -->
|
||||
<section class="mb-10">
|
||||
<h2 class="text-sm uppercase tracking-widest mb-4 opacity-50">Archia Weights</h2>
|
||||
<table class="w-full max-w-2xl border-collapse">
|
||||
<thead>
|
||||
<tr class="text-xs uppercase tracking-widest opacity-50 border-b border-snow/20">
|
||||
<th class="text-left pb-2 pr-8">Weight</th>
|
||||
<th class="text-left pb-2 pr-8">Uppercase</th>
|
||||
<th class="text-left pb-2">Sentence case</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="font-archia">
|
||||
<tr class="border-b border-snow/10">
|
||||
<td class="py-3 pr-8 text-xs opacity-50">Thin 100</td>
|
||||
<td class="py-3 pr-8 text-xl uppercase" style="font-weight: 100">QUMO DATA</td>
|
||||
<td class="py-3 text-xl" style="font-weight: 100">Qumo data analytics</td>
|
||||
</tr>
|
||||
<tr class="border-b border-snow/10">
|
||||
<td class="py-3 pr-8 text-xs opacity-50">Light 300</td>
|
||||
<td class="py-3 pr-8 text-xl uppercase" style="font-weight: 300">QUMO DATA</td>
|
||||
<td class="py-3 text-xl" style="font-weight: 300">Qumo data analytics</td>
|
||||
</tr>
|
||||
<tr class="border-b border-snow/10">
|
||||
<td class="py-3 pr-8 text-xs opacity-50">Regular 400</td>
|
||||
<td class="py-3 pr-8 text-xl uppercase font-normal">QUMO DATA</td>
|
||||
<td class="py-3 text-xl font-normal">Qumo data analytics</td>
|
||||
</tr>
|
||||
<tr class="border-b border-snow/10">
|
||||
<td class="py-3 pr-8 text-xs opacity-50">Medium 500</td>
|
||||
<td class="py-3 pr-8 text-xl uppercase font-medium">QUMO DATA</td>
|
||||
<td class="py-3 text-xl font-medium">Qumo data analytics</td>
|
||||
</tr>
|
||||
<tr class="border-b border-snow/10">
|
||||
<td class="py-3 pr-8 text-xs opacity-50">SemiBold 600</td>
|
||||
<td class="py-3 pr-8 text-xl uppercase font-semibold">QUMO DATA</td>
|
||||
<td class="py-3 text-xl font-semibold">Qumo data analytics</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 pr-8 text-xs opacity-50">Bold 700</td>
|
||||
<td class="py-3 pr-8 text-xl uppercase font-bold">QUMO DATA</td>
|
||||
<td class="py-3 text-xl font-bold">Qumo data analytics</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<p class="text-xs opacity-30 uppercase tracking-widest">Dev artifact — will be replaced by the homepage</p>
|
||||
</main>
|
||||
</BaseLayout>
|
||||
|
||||
62
website/src/styles/global.css
Normal file
62
website/src/styles/global.css
Normal file
@@ -0,0 +1,62 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@theme {
|
||||
--color-midnight: #102022;
|
||||
--color-snow: #F3F3F3;
|
||||
--color-brand-blue: #5257E4;
|
||||
--color-brand-red: #F71E3E;
|
||||
|
||||
--font-archia: "Archia", ui-sans-serif, system-ui, sans-serif;
|
||||
}
|
||||
|
||||
:root {
|
||||
--gradient-brand: linear-gradient(135deg, #5257E4, #F71E3E);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Archia";
|
||||
src: url("../assets/fonts/archia/archia-thin-webfont.woff2") format("woff2");
|
||||
font-weight: 100;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Archia";
|
||||
src: url("../assets/fonts/archia/archia-light-webfont.woff2") format("woff2");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Archia";
|
||||
src: url("../assets/fonts/archia/archia-regular-webfont.woff2") format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Archia";
|
||||
src: url("../assets/fonts/archia/archia-medium-webfont.woff2") format("woff2");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Archia";
|
||||
src: url("../assets/fonts/archia/archia-semibold-webfont.woff2") format("woff2");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Archia";
|
||||
src: url("../assets/fonts/archia/archia-bold-webfont.woff2") format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
Reference in New Issue
Block a user