Szablon witryny, docker i workflow gitea
This commit is contained in:
11
.env.example
Normal file
11
.env.example
Normal file
@@ -0,0 +1,11 @@
|
||||
# Public URL of the website
|
||||
PUBLIC_SITE_URL=https://www.fuz.dariuszm.eu
|
||||
|
||||
# Google Maps
|
||||
PUBLIC_GOOGLE_MAPS_KEY=
|
||||
|
||||
# Contact form API
|
||||
FORMS_ENDPOINT=
|
||||
|
||||
# Astro SSR
|
||||
NODE_ENV=production
|
||||
27
.gitea/workflows/deploy.yml
Normal file
27
.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Deploy FUZ 2.0 to Contabo
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: contabo-runner
|
||||
|
||||
steps:
|
||||
- name: Pull latest code
|
||||
run: |
|
||||
cd /opt/fuz-site
|
||||
git reset --hard HEAD
|
||||
git pull
|
||||
|
||||
- name: Build image
|
||||
run: |
|
||||
cd /opt/fuz-site
|
||||
docker compose -f docker-compose.prod.yml build
|
||||
|
||||
- name: Restart service
|
||||
run: |
|
||||
cd /opt/fuz-site
|
||||
docker compose -f docker-compose.prod.yml up -d
|
||||
44
.gitignore
vendored
Normal file
44
.gitignore
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
# Node
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
pnpm-debug.log*
|
||||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
|
||||
# Astro
|
||||
dist/
|
||||
.astro/
|
||||
.build/
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
||||
|
||||
# Env
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Editor
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
# Docker
|
||||
docker-data/
|
||||
docker-cache/
|
||||
|
||||
# Temp
|
||||
tmp/
|
||||
temp/
|
||||
*.tmp
|
||||
|
||||
# Public generated
|
||||
public/**/*.avif
|
||||
public/**/*.webp
|
||||
public/og/*.txt
|
||||
27
Dockerfile
Normal file
27
Dockerfile
Normal file
@@ -0,0 +1,27 @@
|
||||
# ============================
|
||||
# 1) BUILD STAGE
|
||||
# ============================
|
||||
FROM node:18-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
# ============================
|
||||
# 2) RUNTIME STAGE (alpine)
|
||||
# ============================
|
||||
FROM node:18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder /app /app
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["node", "dist/server/entry.mjs"]
|
||||
12
astro.config.mjs
Normal file
12
astro.config.mjs
Normal file
@@ -0,0 +1,12 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import tailwind from '@astrojs/tailwind';
|
||||
|
||||
export default defineConfig({
|
||||
srcDir: 'src',
|
||||
output: 'server',
|
||||
integrations: [
|
||||
tailwind({
|
||||
applyBaseStyles: true
|
||||
})
|
||||
]
|
||||
});
|
||||
19
docker-compose.prod.yml
Normal file
19
docker-compose.prod.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
fuz-site:
|
||||
build:
|
||||
context: /opt/fuz-site
|
||||
dockerfile: Dockerfile
|
||||
container_name: fuz-site
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- .env
|
||||
ports:
|
||||
- "4000:3000"
|
||||
networks:
|
||||
- n8n_default
|
||||
|
||||
networks:
|
||||
n8n_default:
|
||||
external: true
|
||||
20
package.json
Normal file
20
package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "fuz20",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^4.0.0",
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/tailwind": "^5.0.0",
|
||||
"tailwindcss": "^3.4.0",
|
||||
"autoprefixer": "^10.4.0",
|
||||
"postcss": "^8.4.0"
|
||||
}
|
||||
}
|
||||
6
postcss.config.cjs
Normal file
6
postcss.config.cjs
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
}
|
||||
};
|
||||
4
public/favicon.svg
Normal file
4
public/favicon.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<rect width="64" height="64" rx="12" fill="#0ea5e9"/>
|
||||
<text x="50%" y="50%" text-anchor="middle" dominant-baseline="central" font-size="32" fill="white" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif">F</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 317 B |
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;
|
||||
}
|
||||
15
tailwind.config.cjs
Normal file
15
tailwind.config.cjs
Normal file
@@ -0,0 +1,15 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
"./src/**/*.{astro,html,js,jsx,ts,tsx,vue}"
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
container: {
|
||||
center: true,
|
||||
padding: "1rem"
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: []
|
||||
};
|
||||
12
tsconfig.json
Normal file
12
tsconfig.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@layouts/*": ["src/layouts/*"],
|
||||
"@components/*": ["src/components/*"],
|
||||
"@styles/*": ["src/styles/*"],
|
||||
"@content/*": ["src/content/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user