Szablon witryny, docker i workflow gitea
This commit is contained in:
63
src/components/hero/Hero.astro
Normal file
63
src/components/hero/Hero.astro
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
const {
|
||||
title = [],
|
||||
subtitle = [],
|
||||
description,
|
||||
imageUrl,
|
||||
ctas = []
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<section class="fuz-section">
|
||||
<div class="fuz-container grid md:grid-cols-2 gap-10 items-center">
|
||||
<div class="space-y-6">
|
||||
{Array.isArray(title) ? (
|
||||
<h1 class="fuz-hero-title">
|
||||
{title.map((line) => (
|
||||
<span class="block">{line}</span>
|
||||
))}
|
||||
</h1>
|
||||
) : (
|
||||
<h1 class="fuz-hero-title">{title}</h1>
|
||||
)}
|
||||
|
||||
{Array.isArray(subtitle) && subtitle.length > 0 && (
|
||||
<div class="fuz-hero-subtitle space-y-1">
|
||||
{subtitle.map((line) => (
|
||||
<p>{line}</p>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{description && (
|
||||
<p class="mt-4 text-base md:text-lg text-gray-600 dark:text-gray-300 max-w-xl">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{ctas.length > 0 && (
|
||||
<div class="mt-6 flex flex-wrap gap-3">
|
||||
{ctas.map((cta) => (
|
||||
<a
|
||||
href={cta.href}
|
||||
class="inline-flex items-center rounded-full px-5 py-2.5 text-sm font-medium bg-sky-600 text-white hover:bg-sky-700 dark:bg-sky-500 dark:hover:bg-sky-400"
|
||||
>
|
||||
{cta.label}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{imageUrl && (
|
||||
<div class="relative aspect-video md:aspect-[4/3] overflow-hidden rounded-3xl border border-slate-200/70 dark:border-slate-700/70">
|
||||
<img
|
||||
src={imageUrl}
|
||||
alt=""
|
||||
loading="lazy"
|
||||
class="h-full w-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
10
src/components/layout/Footer.astro
Normal file
10
src/components/layout/Footer.astro
Normal file
@@ -0,0 +1,10 @@
|
||||
<footer class="fuz-footer">
|
||||
<div class="fuz-container flex flex-col md:flex-row items-center justify-between gap-3">
|
||||
<p class="fuz-footer-text">
|
||||
© {new Date().getFullYear()} FUZ – lokalny operator internetu i telewizji.
|
||||
</p>
|
||||
<p class="text-xs text-gray-400">
|
||||
RODO • Polityka prywatności • Cookies
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
29
src/components/layout/Header.astro
Normal file
29
src/components/layout/Header.astro
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
const nav = [
|
||||
{ href: "/", label: "Strona główna" },
|
||||
{ href: "/internet", label: "Internet" },
|
||||
{ href: "/telewizja", label: "Telewizja" },
|
||||
{ href: "/internet-telewizja", label: "Internet + TV" },
|
||||
{ href: "/mapa-zasiegu", label: "Mapa zasięgu" },
|
||||
{ href: "/kontakt", label: "Kontakt" }
|
||||
];
|
||||
---
|
||||
|
||||
<header class="fuz-header">
|
||||
<div class="fuz-container flex items-center justify-between py-3">
|
||||
<a href="/" class="flex items-center gap-2 font-semibold">
|
||||
<span class="inline-flex h-8 w-8 items-center justify-center rounded-full bg-sky-500 text-white text-sm font-bold">
|
||||
F
|
||||
</span>
|
||||
<span>FUZ</span>
|
||||
</a>
|
||||
|
||||
<nav class="hidden md:flex items-center gap-6 text-sm">
|
||||
{nav.map((item) => (
|
||||
<a href={item.href} class="hover:text-sky-600 dark:hover:text-sky-400">
|
||||
{item.label}
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
21
src/components/ui/Button.astro
Normal file
21
src/components/ui/Button.astro
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
const { href, variant = "primary" } = Astro.props;
|
||||
|
||||
const base =
|
||||
"inline-flex items-center justify-center rounded-full px-4 py-2 text-sm font-medium transition";
|
||||
const variants = {
|
||||
primary: "bg-sky-600 text-white hover:bg-sky-700 dark:bg-sky-500 dark:hover:bg-sky-400",
|
||||
secondary: "bg-slate-100 text-slate-900 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-100"
|
||||
};
|
||||
const classes = `${base} ${variants[variant] ?? variants.primary}`;
|
||||
---
|
||||
|
||||
{href ? (
|
||||
<a href={href} class={classes}>
|
||||
<slot />
|
||||
</a>
|
||||
) : (
|
||||
<button type="button" class={classes}>
|
||||
<slot />
|
||||
</button>
|
||||
)}
|
||||
15
src/components/ui/Toast.astro
Normal file
15
src/components/ui/Toast.astro
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
const { message, type = "success" } = Astro.props;
|
||||
|
||||
const base = "fixed right-4 top-20 z-50 rounded-xl px-4 py-3 text-sm shadow-lg border backdrop-blur";
|
||||
const variants = {
|
||||
success: "bg-emerald-50/90 border-emerald-200 text-emerald-900 dark:bg-emerald-900/70 dark:border-emerald-700 dark:text-emerald-50",
|
||||
error: "bg-rose-50/90 border-rose-200 text-rose-900 dark:bg-rose-900/70 dark:border-rose-700 dark:text-rose-50",
|
||||
info: "bg-sky-50/90 border-sky-200 text-sky-900 dark:bg-sky-900/70 dark:border-sky-700 dark:text-sky-50"
|
||||
};
|
||||
const classes = `${base} ${variants[type] ?? variants.success}`;
|
||||
---
|
||||
|
||||
<div class={classes}>
|
||||
{message}
|
||||
</div>
|
||||
13
src/content/home/hero.yaml
Normal file
13
src/content/home/hero.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
title:
|
||||
- "Dlaczego FUZ?"
|
||||
subtitle:
|
||||
- "Lokalny operator – znamy Twoją okolicę"
|
||||
- "Realny serwis, szybkie wsparcie"
|
||||
- "Stabilna infrastruktura światłowodowa i radiowa"
|
||||
description: "Internet i telewizja od ludzi, którzy naprawdę są na miejscu. Bez infolinii z końca świata."
|
||||
imageUrl: "/images/hero/fiber-example.jpg"
|
||||
ctas:
|
||||
- label: "Sprawdź dostępność"
|
||||
href: "/mapa-zasiegu"
|
||||
- label: "Zobacz ofertę"
|
||||
href: "/oferta"
|
||||
16
src/content/seo/home.yaml
Normal file
16
src/content/seo/home.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
title: "FUZ – Internet i telewizja w Twojej okolicy"
|
||||
description: "Lokalny operator internetu i telewizji. Nowoczesny światłowód i radio, realny serwis i szybkie wsparcie."
|
||||
canonical: "/"
|
||||
image: "/og/fuz-home.png"
|
||||
keywords:
|
||||
- internet
|
||||
- światłowód
|
||||
- telewizja
|
||||
- lokalny operator
|
||||
schema:
|
||||
"@context": "https://schema.org"
|
||||
"@type": "Organization"
|
||||
name: "FUZ"
|
||||
url: "https://www.fuz.pl"
|
||||
sameAs:
|
||||
- "https://www.facebook.com"
|
||||
1
src/env.d.ts
vendored
Normal file
1
src/env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference path="../.astro/types.d.ts" />
|
||||
43
src/layouts/BaseHead.astro
Normal file
43
src/layouts/BaseHead.astro
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
const { seo } = Astro.props;
|
||||
|
||||
const {
|
||||
title = "FUZ",
|
||||
description = "Lokalny operator internetu i telewizji.",
|
||||
canonical = "/",
|
||||
image = "/og/default.png",
|
||||
keywords = [],
|
||||
schema = {}
|
||||
} = seo ?? {};
|
||||
---
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
{keywords.length > 0 && (
|
||||
<meta name="keywords" content={keywords.join(", ")} />
|
||||
)}
|
||||
|
||||
<link rel="canonical" href={canonical} />
|
||||
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:image" content={image} />
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content={title} />
|
||||
<meta name="twitter:description" content={description} />
|
||||
<meta name="twitter:image" content={image} />
|
||||
|
||||
{Object.keys(schema).length > 0 && (
|
||||
<script type="application/ld+json">
|
||||
{JSON.stringify(schema)}
|
||||
</script>
|
||||
)}
|
||||
|
||||
<slot />
|
||||
</head>
|
||||
22
src/layouts/DefaultLayout.astro
Normal file
22
src/layouts/DefaultLayout.astro
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
import "../styles/base.css";
|
||||
import BaseHead from "./BaseHead.astro";
|
||||
import Header from "../components/layout/Header.astro";
|
||||
import Footer from "../components/layout/Footer.astro";
|
||||
|
||||
const { seo } = Astro.props;
|
||||
---
|
||||
|
||||
<html lang="pl" class="scroll-smooth">
|
||||
<BaseHead seo={seo} />
|
||||
|
||||
<body class="min-h-screen flex flex-col">
|
||||
<Header />
|
||||
|
||||
<main class="flex-1">
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
14
src/pages/index.astro
Normal file
14
src/pages/index.astro
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
import DefaultLayout from "../layouts/DefaultLayout.astro";
|
||||
import Hero from "../components/hero/Hero.astro";
|
||||
|
||||
import yaml from "js-yaml";
|
||||
import fs from "fs";
|
||||
|
||||
const seo = yaml.load(fs.readFileSync("./src/content/seo/home.yaml", "utf8"));
|
||||
const hero = yaml.load(fs.readFileSync("./src/content/home/hero.yaml", "utf8"));
|
||||
---
|
||||
|
||||
<DefaultLayout seo={seo}>
|
||||
<Hero {...hero} />
|
||||
</DefaultLayout>
|
||||
20
src/pages/internet-telewizja/index.astro
Normal file
20
src/pages/internet-telewizja/index.astro
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
import DefaultLayout from "../../layouts/DefaultLayout.astro";
|
||||
|
||||
const seo = {
|
||||
title: "Internet + Telewizja – FUZ",
|
||||
description: "Internet + Telewizja – FUZ",
|
||||
canonical: "/internet-telewizja"
|
||||
};
|
||||
---
|
||||
|
||||
<DefaultLayout seo={seo}>
|
||||
<section class="fuz-section">
|
||||
<div class="fuz-container">
|
||||
<h1 class="fuz-hero-title">Internet + Telewizja – FUZ</h1>
|
||||
<p class="mt-4 text-gray-600 dark:text-gray-300">
|
||||
Ta podstrona jest na razie szkieletem. Możemy tu później wczytać treść z YAML.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</DefaultLayout>
|
||||
20
src/pages/internet/index.astro
Normal file
20
src/pages/internet/index.astro
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
import DefaultLayout from "../../layouts/DefaultLayout.astro";
|
||||
|
||||
const seo = {
|
||||
title: "Internet – FUZ",
|
||||
description: "Internet – FUZ",
|
||||
canonical: "/internet"
|
||||
};
|
||||
---
|
||||
|
||||
<DefaultLayout seo={seo}>
|
||||
<section class="fuz-section">
|
||||
<div class="fuz-container">
|
||||
<h1 class="fuz-hero-title">Internet – FUZ</h1>
|
||||
<p class="mt-4 text-gray-600 dark:text-gray-300">
|
||||
Ta podstrona jest na razie szkieletem. Możemy tu później wczytać treść z YAML.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</DefaultLayout>
|
||||
20
src/pages/kontakt/index.astro
Normal file
20
src/pages/kontakt/index.astro
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
import DefaultLayout from "../../layouts/DefaultLayout.astro";
|
||||
|
||||
const seo = {
|
||||
title: "Kontakt – FUZ",
|
||||
description: "Kontakt – FUZ",
|
||||
canonical: "/kontakt"
|
||||
};
|
||||
---
|
||||
|
||||
<DefaultLayout seo={seo}>
|
||||
<section class="fuz-section">
|
||||
<div class="fuz-container">
|
||||
<h1 class="fuz-hero-title">Kontakt – FUZ</h1>
|
||||
<p class="mt-4 text-gray-600 dark:text-gray-300">
|
||||
Ta podstrona jest na razie szkieletem. Możemy tu później wczytać treść z YAML.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</DefaultLayout>
|
||||
20
src/pages/mapa-zasiegu/index.astro
Normal file
20
src/pages/mapa-zasiegu/index.astro
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
import DefaultLayout from "../../layouts/DefaultLayout.astro";
|
||||
|
||||
const seo = {
|
||||
title: "Mapa zasięgu – FUZ",
|
||||
description: "Mapa zasięgu – FUZ",
|
||||
canonical: "/mapa-zasiegu"
|
||||
};
|
||||
---
|
||||
|
||||
<DefaultLayout seo={seo}>
|
||||
<section class="fuz-section">
|
||||
<div class="fuz-container">
|
||||
<h1 class="fuz-hero-title">Mapa zasięgu – FUZ</h1>
|
||||
<p class="mt-4 text-gray-600 dark:text-gray-300">
|
||||
Ta podstrona jest na razie szkieletem. Możemy tu później wczytać treść z YAML.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</DefaultLayout>
|
||||
20
src/pages/oferta/index.astro
Normal file
20
src/pages/oferta/index.astro
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
import DefaultLayout from "../../layouts/DefaultLayout.astro";
|
||||
|
||||
const seo = {
|
||||
title: "Oferta – FUZ",
|
||||
description: "Oferta – FUZ",
|
||||
canonical: "/oferta"
|
||||
};
|
||||
---
|
||||
|
||||
<DefaultLayout seo={seo}>
|
||||
<section class="fuz-section">
|
||||
<div class="fuz-container">
|
||||
<h1 class="fuz-hero-title">Oferta – FUZ</h1>
|
||||
<p class="mt-4 text-gray-600 dark:text-gray-300">
|
||||
Ta podstrona jest na razie szkieletem. Możemy tu później wczytać treść z YAML.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</DefaultLayout>
|
||||
20
src/pages/telewizja/index.astro
Normal file
20
src/pages/telewizja/index.astro
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
import DefaultLayout from "../../layouts/DefaultLayout.astro";
|
||||
|
||||
const seo = {
|
||||
title: "Telewizja – FUZ",
|
||||
description: "Telewizja – FUZ",
|
||||
canonical: "/telewizja"
|
||||
};
|
||||
---
|
||||
|
||||
<DefaultLayout seo={seo}>
|
||||
<section class="fuz-section">
|
||||
<div class="fuz-container">
|
||||
<h1 class="fuz-hero-title">Telewizja – FUZ</h1>
|
||||
<p class="mt-4 text-gray-600 dark:text-gray-300">
|
||||
Ta podstrona jest na razie szkieletem. Możemy tu później wczytać treść z YAML.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</DefaultLayout>
|
||||
1
src/styles/base.css
Normal file
1
src/styles/base.css
Normal file
@@ -0,0 +1 @@
|
||||
@import "./tailwind.css";
|
||||
36
src/styles/tailwind.css
Normal file
36
src/styles/tailwind.css
Normal file
@@ -0,0 +1,36 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-white text-gray-900 dark:bg-slate-900 dark:text-gray-100 antialiased;
|
||||
}
|
||||
|
||||
/* Simple FUZ section helpers */
|
||||
.fuz-section {
|
||||
@apply py-16 md:py-24;
|
||||
}
|
||||
|
||||
.fuz-container {
|
||||
@apply container mx-auto px-4;
|
||||
}
|
||||
|
||||
.fuz-hero-title {
|
||||
@apply text-3xl md:text-5xl font-bold tracking-tight;
|
||||
}
|
||||
|
||||
.fuz-hero-subtitle {
|
||||
@apply mt-4 text-lg md:text-xl text-gray-600 dark:text-gray-300;
|
||||
}
|
||||
|
||||
.fuz-header {
|
||||
@apply border-b border-slate-200/60 dark:border-slate-700/60 bg-white/70 dark:bg-slate-900/70 backdrop-blur;
|
||||
}
|
||||
|
||||
.fuz-footer {
|
||||
@apply border-t border-slate-200/60 dark:border-slate-700/60 py-6 mt-10 text-sm text-gray-500 dark:text-gray-400;
|
||||
}
|
||||
Reference in New Issue
Block a user