Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fd8f068594 | |||
| 00bafa761b |
@@ -29,6 +29,7 @@ jobs:
|
|||||||
gatekeeper_host: ${{ steps.determine.outputs.gatekeeper_host }}
|
gatekeeper_host: ${{ steps.determine.outputs.gatekeeper_host }}
|
||||||
traefik_rule: ${{ steps.determine.outputs.traefik_rule }}
|
traefik_rule: ${{ steps.determine.outputs.traefik_rule }}
|
||||||
gatekeeper_rule: ${{ steps.determine.outputs.gatekeeper_rule }}
|
gatekeeper_rule: ${{ steps.determine.outputs.gatekeeper_rule }}
|
||||||
|
traefik_middlewares: ${{ steps.determine.outputs.traefik_middlewares }}
|
||||||
project_name: ${{ steps.determine.outputs.project_name }}
|
project_name: ${{ steps.determine.outputs.project_name }}
|
||||||
steps:
|
steps:
|
||||||
- name: 🔍 Debug Info
|
- name: 🔍 Debug Info
|
||||||
@@ -114,9 +115,11 @@ jobs:
|
|||||||
if [[ "$TARGET" == "production" ]]; then
|
if [[ "$TARGET" == "production" ]]; then
|
||||||
TRAEFIK_RULE="Host(\`${DOMAIN_BASE}\`) || Host(\`www.${DOMAIN_BASE}\`)"
|
TRAEFIK_RULE="Host(\`${DOMAIN_BASE}\`) || Host(\`www.${DOMAIN_BASE}\`)"
|
||||||
GATEKEEPER_RULE="(Host(\`${DOMAIN_BASE}\`) || Host(\`www.${DOMAIN_BASE}\`)) && PathPrefix(\`/gatekeeper\`) || Host(\`gatekeeper.${DOMAIN_BASE}\`)"
|
GATEKEEPER_RULE="(Host(\`${DOMAIN_BASE}\`) || Host(\`www.${DOMAIN_BASE}\`)) && PathPrefix(\`/gatekeeper\`) || Host(\`gatekeeper.${DOMAIN_BASE}\`)"
|
||||||
|
TRAEFIK_MIDDLEWARES="compress"
|
||||||
else
|
else
|
||||||
TRAEFIK_RULE="Host(\`${TRAEFIK_HOST}\`)"
|
TRAEFIK_RULE="Host(\`${TRAEFIK_HOST}\`)"
|
||||||
GATEKEEPER_RULE="(Host(\`${TRAEFIK_HOST}\`) && PathPrefix(\`/gatekeeper\`)) || Host(\`gatekeeper.${TRAEFIK_HOST}\`)"
|
GATEKEEPER_RULE="(Host(\`${TRAEFIK_HOST}\`) && PathPrefix(\`/gatekeeper\`)) || Host(\`gatekeeper.${TRAEFIK_HOST}\`)"
|
||||||
|
TRAEFIK_MIDDLEWARES="${PRJ_ID}-${TARGET}-auth"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -129,6 +132,7 @@ jobs:
|
|||||||
echo "traefik_host=$TRAEFIK_HOST" >> "$GITHUB_OUTPUT"
|
echo "traefik_host=$TRAEFIK_HOST" >> "$GITHUB_OUTPUT"
|
||||||
echo "traefik_rule=$TRAEFIK_RULE" >> "$GITHUB_OUTPUT"
|
echo "traefik_rule=$TRAEFIK_RULE" >> "$GITHUB_OUTPUT"
|
||||||
echo "gatekeeper_rule=$GATEKEEPER_RULE" >> "$GITHUB_OUTPUT"
|
echo "gatekeeper_rule=$GATEKEEPER_RULE" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "traefik_middlewares=$TRAEFIK_MIDDLEWARES" >> "$GITHUB_OUTPUT"
|
||||||
echo "gatekeeper_host=$GATEKEEPER_HOST" >> "$GITHUB_OUTPUT"
|
echo "gatekeeper_host=$GATEKEEPER_HOST" >> "$GITHUB_OUTPUT"
|
||||||
echo "next_public_base_url=$NEXT_PUBLIC_BASE_URL" >> "$GITHUB_OUTPUT"
|
echo "next_public_base_url=$NEXT_PUBLIC_BASE_URL" >> "$GITHUB_OUTPUT"
|
||||||
echo "directus_url=$DIRECTUS_URL" >> "$GITHUB_OUTPUT"
|
echo "directus_url=$DIRECTUS_URL" >> "$GITHUB_OUTPUT"
|
||||||
@@ -228,6 +232,7 @@ jobs:
|
|||||||
IMAGE_TAG=${{ needs.prepare.outputs.image_tag }}
|
IMAGE_TAG=${{ needs.prepare.outputs.image_tag }}
|
||||||
TRAEFIK_HOST=${{ needs.prepare.outputs.traefik_host }}
|
TRAEFIK_HOST=${{ needs.prepare.outputs.traefik_host }}
|
||||||
TRAEFIK_RULE=${{ needs.prepare.outputs.traefik_rule }}
|
TRAEFIK_RULE=${{ needs.prepare.outputs.traefik_rule }}
|
||||||
|
TRAEFIK_MIDDLEWARES=${{ needs.prepare.outputs.traefik_middlewares }}
|
||||||
GATEKEEPER_RULE=${{ needs.prepare.outputs.gatekeeper_rule }}
|
GATEKEEPER_RULE=${{ needs.prepare.outputs.gatekeeper_rule }}
|
||||||
GATEKEEPER_HOST=${{ needs.prepare.outputs.gatekeeper_host }}
|
GATEKEEPER_HOST=${{ needs.prepare.outputs.gatekeeper_host }}
|
||||||
PROJECT_NAME=${{ needs.prepare.outputs.project_name }}
|
PROJECT_NAME=${{ needs.prepare.outputs.project_name }}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import "../globals.css";
|
|||||||
import { NextIntlClientProvider } from "next-intl";
|
import { NextIntlClientProvider } from "next-intl";
|
||||||
import { getMessages } from "next-intl/server";
|
import { getMessages } from "next-intl/server";
|
||||||
import { notFound } from "next/navigation";
|
import { notFound } from "next/navigation";
|
||||||
|
import { LazyMotion, domAnimation } from "framer-motion";
|
||||||
|
|
||||||
const inter = Inter({
|
const inter = Inter({
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
@@ -122,7 +123,9 @@ export default async function RootLayout({
|
|||||||
</head>
|
</head>
|
||||||
<body className="antialiased">
|
<body className="antialiased">
|
||||||
<NextIntlClientProvider messages={messages}>
|
<NextIntlClientProvider messages={messages}>
|
||||||
<Layout>{children}</Layout>
|
<LazyMotion features={domAnimation}>
|
||||||
|
<Layout>{children}</Layout>
|
||||||
|
</LazyMotion>
|
||||||
</NextIntlClientProvider>
|
</NextIntlClientProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { m, LazyMotion, domAnimation } from "framer-motion";
|
import { m } from "framer-motion";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { ArrowRight } from "lucide-react";
|
import { ArrowRight } from "lucide-react";
|
||||||
|
|
||||||
@@ -62,15 +62,13 @@ export const Button = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const spotlight = (
|
const spotlight = (
|
||||||
<LazyMotion features={domAnimation}>
|
<m.div
|
||||||
<m.div
|
className="absolute inset-0 z-0 pointer-events-none transition-opacity duration-500"
|
||||||
className="absolute inset-0 z-0 pointer-events-none transition-opacity duration-500"
|
style={{
|
||||||
style={{
|
opacity: isHovered ? 1 : 0,
|
||||||
opacity: isHovered ? 1 : 0,
|
background: `radial-gradient(600px circle at ${mousePosition.x}px ${mousePosition.y}px, rgba(255,255,255,0.15), transparent 40%)`,
|
||||||
background: `radial-gradient(600px circle at ${mousePosition.x}px ${mousePosition.y}px, rgba(255,255,255,0.15), transparent 40%)`,
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
|
||||||
</LazyMotion>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const buttonProps = {
|
const buttonProps = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { m, LazyMotion, domAnimation } from "framer-motion";
|
import { m } from "framer-motion";
|
||||||
import {
|
import {
|
||||||
BarChart3,
|
BarChart3,
|
||||||
CheckCircle2,
|
CheckCircle2,
|
||||||
@@ -326,55 +326,53 @@ export default function Home() {
|
|||||||
<div className="tech-corner bottom-8 right-8 border-b-2 border-r-2" />
|
<div className="tech-corner bottom-8 right-8 border-b-2 border-r-2" />
|
||||||
|
|
||||||
<div className="absolute top-0 right-0 w-1/2 h-full opacity-10 pointer-events-none">
|
<div className="absolute top-0 right-0 w-1/2 h-full opacity-10 pointer-events-none">
|
||||||
<LazyMotion features={domAnimation}>
|
<svg
|
||||||
<svg
|
viewBox="0 0 400 400"
|
||||||
viewBox="0 0 400 400"
|
fill="none"
|
||||||
fill="none"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
>
|
||||||
>
|
<m.circle
|
||||||
<m.circle
|
animate={{ r: [400, 410, 400], opacity: [0.1, 0.2, 0.1] }}
|
||||||
animate={{ r: [400, 410, 400], opacity: [0.1, 0.2, 0.1] }}
|
transition={{
|
||||||
transition={{
|
duration: 5,
|
||||||
duration: 5,
|
repeat: Infinity,
|
||||||
repeat: Infinity,
|
ease: "easeInOut",
|
||||||
ease: "easeInOut",
|
}}
|
||||||
}}
|
cx="400"
|
||||||
cx="400"
|
cy="0"
|
||||||
cy="0"
|
r="400"
|
||||||
r="400"
|
stroke="white"
|
||||||
stroke="white"
|
strokeWidth="2"
|
||||||
strokeWidth="2"
|
/>
|
||||||
/>
|
<m.circle
|
||||||
<m.circle
|
animate={{ r: [300, 310, 300], opacity: [0.1, 0.2, 0.1] }}
|
||||||
animate={{ r: [300, 310, 300], opacity: [0.1, 0.2, 0.1] }}
|
transition={{
|
||||||
transition={{
|
duration: 4,
|
||||||
duration: 4,
|
repeat: Infinity,
|
||||||
repeat: Infinity,
|
ease: "easeInOut",
|
||||||
ease: "easeInOut",
|
delay: 0.5,
|
||||||
delay: 0.5,
|
}}
|
||||||
}}
|
cx="400"
|
||||||
cx="400"
|
cy="0"
|
||||||
cy="0"
|
r="300"
|
||||||
r="300"
|
stroke="white"
|
||||||
stroke="white"
|
strokeWidth="2"
|
||||||
strokeWidth="2"
|
/>
|
||||||
/>
|
<m.circle
|
||||||
<m.circle
|
animate={{ r: [200, 210, 200], opacity: [0.1, 0.2, 0.1] }}
|
||||||
animate={{ r: [200, 210, 200], opacity: [0.1, 0.2, 0.1] }}
|
transition={{
|
||||||
transition={{
|
duration: 3,
|
||||||
duration: 3,
|
repeat: Infinity,
|
||||||
repeat: Infinity,
|
ease: "easeInOut",
|
||||||
ease: "easeInOut",
|
delay: 1,
|
||||||
delay: 1,
|
}}
|
||||||
}}
|
cx="400"
|
||||||
cx="400"
|
cy="0"
|
||||||
cy="0"
|
r="200"
|
||||||
r="200"
|
stroke="white"
|
||||||
stroke="white"
|
strokeWidth="2"
|
||||||
strokeWidth="2"
|
/>
|
||||||
/>
|
</svg>
|
||||||
</svg>
|
|
||||||
</LazyMotion>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative z-10">
|
<div className="relative z-10">
|
||||||
|
|||||||
@@ -116,38 +116,36 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
|
|||||||
</Reveal>
|
</Reveal>
|
||||||
|
|
||||||
{/* Mobile Menu Overlay */}
|
{/* Mobile Menu Overlay */}
|
||||||
<LazyMotion features={domAnimation}>
|
<AnimatePresence>
|
||||||
<AnimatePresence>
|
{isMobileMenuOpen && (
|
||||||
{isMobileMenuOpen && (
|
<m.div
|
||||||
<m.div
|
initial={{ opacity: 0, y: -20 }}
|
||||||
initial={{ opacity: 0, y: -20 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
exit={{ opacity: 0, y: -20 }}
|
||||||
exit={{ opacity: 0, y: -20 }}
|
className="fixed inset-0 z-[90] bg-white pt-32 px-6 md:hidden"
|
||||||
className="fixed inset-0 z-[90] bg-white pt-32 px-6 md:hidden"
|
>
|
||||||
>
|
<nav className="flex flex-col gap-4">
|
||||||
<nav className="flex flex-col gap-4">
|
{navLinks.map((link) => (
|
||||||
{navLinks.map((link) => (
|
<Link
|
||||||
<Link
|
key={link.href}
|
||||||
key={link.href}
|
href={link.href}
|
||||||
href={link.href}
|
className={`flex items-center gap-4 p-4 rounded-xl text-lg font-semibold transition-all ${
|
||||||
className={`flex items-center gap-4 p-4 rounded-xl text-lg font-semibold transition-all ${
|
isActive(link.href)
|
||||||
isActive(link.href)
|
? "text-accent bg-accent/5"
|
||||||
? "text-accent bg-accent/5"
|
: "text-slate-600 hover:text-primary hover:bg-slate-50"
|
||||||
: "text-slate-600 hover:text-primary hover:bg-slate-50"
|
}`}
|
||||||
}`}
|
>
|
||||||
>
|
<link.icon size={24} />
|
||||||
<link.icon size={24} />
|
{link.label}
|
||||||
{link.label}
|
</Link>
|
||||||
</Link>
|
))}
|
||||||
))}
|
<Button href="/kontakt" className="mt-4 w-full">
|
||||||
<Button href="/kontakt" className="mt-4 w-full">
|
{t("nav.cta")}
|
||||||
{t("nav.cta")}
|
</Button>
|
||||||
</Button>
|
</nav>
|
||||||
</nav>
|
</m.div>
|
||||||
</m.div>
|
)}
|
||||||
)}
|
</AnimatePresence>
|
||||||
</AnimatePresence>
|
|
||||||
</LazyMotion>
|
|
||||||
|
|
||||||
<main className="flex-grow">{children}</main>
|
<main className="flex-grow">{children}</main>
|
||||||
|
|
||||||
@@ -168,18 +166,16 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
|
|||||||
<div className="absolute inset-0 grid-pattern opacity-[0.08] pointer-events-none" />
|
<div className="absolute inset-0 grid-pattern opacity-[0.08] pointer-events-none" />
|
||||||
|
|
||||||
{/* Animated Tech Lines */}
|
{/* Animated Tech Lines */}
|
||||||
<LazyMotion features={domAnimation}>
|
<m.div
|
||||||
<m.div
|
animate={{ x: ["-100%", "100%"] }}
|
||||||
animate={{ x: ["-100%", "100%"] }}
|
transition={{ duration: 15, repeat: Infinity, ease: "linear" }}
|
||||||
transition={{ duration: 15, repeat: Infinity, ease: "linear" }}
|
className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-accent/30 to-transparent"
|
||||||
className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-accent/30 to-transparent"
|
/>
|
||||||
/>
|
<m.div
|
||||||
<m.div
|
animate={{ x: ["100%", "-100%"] }}
|
||||||
animate={{ x: ["100%", "-100%"] }}
|
transition={{ duration: 20, repeat: Infinity, ease: "linear" }}
|
||||||
transition={{ duration: 20, repeat: Infinity, ease: "linear" }}
|
className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-accent/20 to-transparent"
|
||||||
className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-accent/20 to-transparent"
|
/>
|
||||||
/>
|
|
||||||
</LazyMotion>
|
|
||||||
|
|
||||||
{/* Corner Accents */}
|
{/* Corner Accents */}
|
||||||
<div className="tech-corner top-8 left-8 border-t border-l border-white/10 group-hover:border-accent/30 transition-colors duration-700" />
|
<div className="tech-corner top-8 left-8 border-t border-l border-white/10 group-hover:border-accent/30 transition-colors duration-700" />
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
'use client';
|
"use client";
|
||||||
|
|
||||||
import React from 'react';
|
import React from "react";
|
||||||
import { m, LazyMotion, domAnimation } from 'framer-motion';
|
import { m } from "framer-motion";
|
||||||
|
|
||||||
interface RevealProps {
|
interface RevealProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
delay?: number;
|
delay?: number;
|
||||||
direction?: 'up' | 'down' | 'left' | 'right';
|
direction?: "up" | "down" | "left" | "right";
|
||||||
fullWidth?: boolean;
|
fullWidth?: boolean;
|
||||||
viewportMargin?: string;
|
viewportMargin?: string;
|
||||||
trigger?: 'inView' | 'mount';
|
trigger?: "inView" | "mount";
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Reveal = ({
|
export const Reveal = ({
|
||||||
children,
|
children,
|
||||||
className = '',
|
className = "",
|
||||||
delay = 0,
|
delay = 0,
|
||||||
direction = 'up',
|
direction = "up",
|
||||||
fullWidth = false,
|
fullWidth = false,
|
||||||
viewportMargin = "-50px",
|
viewportMargin = "-50px",
|
||||||
trigger = 'inView'
|
trigger = "inView",
|
||||||
}: RevealProps) => {
|
}: RevealProps) => {
|
||||||
const directions = {
|
const directions = {
|
||||||
up: { y: 30 },
|
up: { y: 30 },
|
||||||
@@ -30,35 +30,45 @@ export const Reveal = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LazyMotion features={domAnimation}>
|
|
||||||
<m.div
|
<m.div
|
||||||
initial={{
|
initial={{
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
...directions[direction]
|
...directions[direction],
|
||||||
}}
|
}}
|
||||||
animate={trigger === 'mount' ? {
|
animate={
|
||||||
opacity: 1,
|
trigger === "mount"
|
||||||
x: 0,
|
? {
|
||||||
y: 0
|
opacity: 1,
|
||||||
} : undefined}
|
x: 0,
|
||||||
whileInView={trigger === 'inView' ? {
|
y: 0,
|
||||||
opacity: 1,
|
}
|
||||||
x: 0,
|
: undefined
|
||||||
y: 0
|
}
|
||||||
} : undefined}
|
whileInView={
|
||||||
viewport={trigger === 'inView' ? { once: true, margin: viewportMargin } : undefined}
|
trigger === "inView"
|
||||||
|
? {
|
||||||
|
opacity: 1,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
viewport={
|
||||||
|
trigger === "inView"
|
||||||
|
? { once: true, margin: viewportMargin }
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
transition={{
|
transition={{
|
||||||
type: "spring",
|
type: "spring",
|
||||||
stiffness: 50,
|
stiffness: 50,
|
||||||
damping: 20,
|
damping: 20,
|
||||||
mass: 1,
|
mass: 1,
|
||||||
delay: delay
|
delay: delay,
|
||||||
}}
|
}}
|
||||||
className={`${fullWidth ? 'w-full' : ''} ${className} motion-fix`}
|
className={`${fullWidth ? "w-full" : ""} ${className} motion-fix will-change-[transform,opacity]`}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</m.div>
|
</m.div>
|
||||||
</LazyMotion>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -68,13 +78,12 @@ interface StaggerProps {
|
|||||||
staggerDelay?: number;
|
staggerDelay?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Stagger = ({
|
export const Stagger = ({
|
||||||
children,
|
children,
|
||||||
className = '',
|
className = "",
|
||||||
staggerDelay = 0.1
|
staggerDelay = 0.1,
|
||||||
}: StaggerProps) => {
|
}: StaggerProps) => {
|
||||||
return (
|
return (
|
||||||
<LazyMotion features={domAnimation}>
|
|
||||||
<m.div
|
<m.div
|
||||||
initial="initial"
|
initial="initial"
|
||||||
whileInView="animate"
|
whileInView="animate"
|
||||||
@@ -90,6 +99,5 @@ export const Stagger = ({
|
|||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</m.div>
|
</m.div>
|
||||||
</LazyMotion>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
"use client";
|
||||||
|
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from "react";
|
||||||
import { m, LazyMotion, domAnimation } from 'framer-motion';
|
import { m } from "framer-motion";
|
||||||
|
|
||||||
export const TileGrid = () => {
|
export const TileGrid = () => {
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
@@ -12,42 +12,41 @@ export const TileGrid = () => {
|
|||||||
|
|
||||||
if (!mounted) return null;
|
if (!mounted) return null;
|
||||||
|
|
||||||
const rows = 15;
|
const rows = 7;
|
||||||
const cols = 20;
|
const cols = 8;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="absolute inset-0 pointer-events-none overflow-hidden z-[1]">
|
<div className="absolute inset-0 pointer-events-none overflow-hidden z-[1]">
|
||||||
<LazyMotion features={domAnimation}>
|
<div className="flex flex-col gap-8 md:gap-12 min-w-[120%] min-h-[120%] -left-[10%] -top-[10%] absolute">
|
||||||
<div className="flex flex-col gap-3 min-w-[120%] min-h-[120%] -left-[10%] -top-[10%] absolute">
|
|
||||||
{[...Array(rows)].map((_, rowIndex) => (
|
{[...Array(rows)].map((_, rowIndex) => (
|
||||||
<div
|
<div
|
||||||
key={rowIndex}
|
key={rowIndex}
|
||||||
className="flex gap-3 justify-center"
|
className="flex gap-8 md:gap-12 justify-center"
|
||||||
style={{
|
style={{
|
||||||
transform: rowIndex % 2 === 0 ? 'translateX(0)' : 'translateX(80px)',
|
transform:
|
||||||
|
rowIndex % 2 === 0 ? "translateX(0)" : "translateX(100px)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{[...Array(cols)].map((_, colIndex) => (
|
{[...Array(cols)].map((_, colIndex) => (
|
||||||
<m.div
|
<m.div
|
||||||
key={`${rowIndex}-${colIndex}`}
|
key={`${rowIndex}-${colIndex}`}
|
||||||
initial={{ opacity: 0.05 }}
|
initial={{ opacity: 0.03 }}
|
||||||
animate={{
|
animate={{
|
||||||
opacity: [0.05, Math.random() > 0.9 ? 0.25 : 0.05, 0.05],
|
opacity: [0.03, Math.random() > 0.8 ? 0.15 : 0.03, 0.03],
|
||||||
scale: [1, Math.random() > 0.9 ? 1.05 : 1, 1]
|
scale: [1, Math.random() > 0.8 ? 1.02 : 1, 1],
|
||||||
}}
|
}}
|
||||||
transition={{
|
transition={{
|
||||||
duration: 5 + Math.random() * 5,
|
duration: 8 + Math.random() * 8,
|
||||||
repeat: Infinity,
|
repeat: Infinity,
|
||||||
delay: Math.random() * 20,
|
delay: Math.random() * 15,
|
||||||
ease: "easeInOut"
|
ease: "easeInOut",
|
||||||
}}
|
}}
|
||||||
className="w-24 h-24 md:w-40 md:h-40 bg-white/10 backdrop-blur-[2px] rounded-2xl md:rounded-3xl border border-white/20 shadow-[0_8px_32px_0_rgba(31,38,135,0.07)] shrink-0"
|
className="w-32 h-32 md:w-56 md:h-56 bg-white/5 rounded-3xl md:rounded-[3rem] border border-white/10 shadow-[0_8px_32px_0_rgba(31,38,135,0.03)] shrink-0 will-change-transform"
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</LazyMotion>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ services:
|
|||||||
- "traefik.http.routers.${PROJECT_NAME}.tls.certresolver=le"
|
- "traefik.http.routers.${PROJECT_NAME}.tls.certresolver=le"
|
||||||
- "traefik.http.routers.${PROJECT_NAME}.tls=true"
|
- "traefik.http.routers.${PROJECT_NAME}.tls=true"
|
||||||
- "traefik.http.services.${PROJECT_NAME}.loadbalancer.server.port=3000"
|
- "traefik.http.services.${PROJECT_NAME}.loadbalancer.server.port=3000"
|
||||||
- "traefik.http.routers.${PROJECT_NAME}.middlewares=${PROJECT_NAME}-auth"
|
- "traefik.http.routers.${PROJECT_NAME}.middlewares=${TRAEFIK_MIDDLEWARES:-${PROJECT_NAME}-auth}"
|
||||||
- "traefik.docker.network=infra"
|
- "traefik.docker.network=infra"
|
||||||
|
|
||||||
# Gatekeeper Router (Shared Host + dedicated Subdomain)
|
# Gatekeeper Router (Shared Host + dedicated Subdomain)
|
||||||
|
|||||||
Reference in New Issue
Block a user