feat: implement premium eco-futurism climate tech portal
@@ -0,0 +1,55 @@
|
|||||||
|
# 1. Base image
|
||||||
|
FROM node:20-alpine AS base
|
||||||
|
|
||||||
|
# 2. Dependencies
|
||||||
|
FROM base AS deps
|
||||||
|
RUN apk add --no-cache libc6-compat
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install dependencies based on the preferred package manager
|
||||||
|
COPY package.json package-lock.json* ./
|
||||||
|
RUN npm ci --legacy-peer-deps
|
||||||
|
|
||||||
|
|
||||||
|
# 3. Builder
|
||||||
|
FROM base AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Environment variables must be present at build time for Next.js
|
||||||
|
# Coolify will provide these, but we can set defaults
|
||||||
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# 4. Runner
|
||||||
|
FROM base AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
|
RUN addgroup --system --gid 1001 nodejs
|
||||||
|
RUN adduser --system --uid 1001 nextjs
|
||||||
|
|
||||||
|
COPY --from=builder /app/public ./public
|
||||||
|
|
||||||
|
# Set the correct permission for prerender cache
|
||||||
|
RUN mkdir .next
|
||||||
|
RUN chown nextjs:nodejs .next
|
||||||
|
|
||||||
|
# Automatically leverage output traces to reduce image size
|
||||||
|
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||||
|
|
||||||
|
USER nextjs
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
ENV PORT=3000
|
||||||
|
# set hostname to localhost
|
||||||
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
|
CMD ["node", "server.js"]
|
||||||
@@ -1,26 +1,135 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--background: #ffffff;
|
--background: #03070b;
|
||||||
--foreground: #171717;
|
--foreground: #f8fafc;
|
||||||
|
|
||||||
|
--bg-primary: #03070b;
|
||||||
|
--bg-secondary: #070d14;
|
||||||
|
--bg-tertiary: #0c141d;
|
||||||
|
|
||||||
|
--color-emerald: #0df293;
|
||||||
|
--color-emerald-dim: rgba(13, 242, 147, 0.15);
|
||||||
|
--color-cyan: #00f2fe;
|
||||||
|
--color-cyan-dim: rgba(0, 242, 254, 0.15);
|
||||||
|
|
||||||
|
--text-primary: #f8fafc;
|
||||||
|
--text-secondary: #94a3b8;
|
||||||
|
--text-dim: #64748b;
|
||||||
|
|
||||||
|
--border-glow: rgba(13, 242, 147, 0.15);
|
||||||
|
--border-cyan-glow: rgba(0, 242, 254, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme inline {
|
@theme {
|
||||||
--color-background: var(--background);
|
--color-bg-primary: var(--bg-primary);
|
||||||
--color-foreground: var(--foreground);
|
--color-bg-secondary: var(--bg-secondary);
|
||||||
--font-sans: var(--font-geist-sans);
|
--color-bg-tertiary: var(--bg-tertiary);
|
||||||
--font-mono: var(--font-geist-mono);
|
|
||||||
|
--color-accent-emerald: var(--color-emerald);
|
||||||
|
--color-accent-emerald-dim: var(--color-emerald-dim);
|
||||||
|
--color-accent-cyan: var(--color-cyan);
|
||||||
|
--color-accent-cyan-dim: var(--color-cyan-dim);
|
||||||
|
|
||||||
|
--color-text-primary: var(--text-primary);
|
||||||
|
--color-text-secondary: var(--text-secondary);
|
||||||
|
--color-text-dim: var(--text-dim);
|
||||||
|
|
||||||
|
--font-space: var(--font-space-grotesk);
|
||||||
|
--font-outfit: var(--font-outfit);
|
||||||
|
|
||||||
|
--animate-pulse-slow: pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||||
|
--animate-spin-slow: spin 20s linear infinite;
|
||||||
|
--animate-float: float 6s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@keyframes float {
|
||||||
:root {
|
0%, 100% {
|
||||||
--background: #0a0a0a;
|
transform: translateY(0);
|
||||||
--foreground: #ededed;
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-10px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Base resets & layouts */
|
||||||
body {
|
body {
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
color: var(--foreground);
|
color: var(--foreground);
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
overflow-x: hidden;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom premium utilities */
|
||||||
|
.glow-text-emerald {
|
||||||
|
text-shadow: 0 0 20px rgba(13, 242, 147, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glow-text-cyan {
|
||||||
|
text-shadow: 0 0 20px rgba(0, 242, 254, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-glow-emerald {
|
||||||
|
border-color: var(--border-glow);
|
||||||
|
box-shadow: 0 0 15px rgba(13, 242, 147, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-glow-cyan {
|
||||||
|
border-color: var(--border-cyan-glow);
|
||||||
|
box-shadow: 0 0 15px rgba(0, 242, 254, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-panel {
|
||||||
|
background: rgba(7, 13, 20, 0.7);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
-webkit-backdrop-filter: blur(12px);
|
||||||
|
border: 1px solid rgba(13, 242, 147, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-panel-cyan {
|
||||||
|
background: rgba(7, 13, 20, 0.7);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
-webkit-backdrop-filter: blur(12px);
|
||||||
|
border: 1px solid rgba(0, 242, 254, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom scrollbars */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: var(--bg-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--bg-tertiary);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: var(--color-emerald);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lenis smooth scroll fix */
|
||||||
|
html.lenis, html.lenis body {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lenis.lenis-smooth {
|
||||||
|
scroll-behavior: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lenis.lenis-smooth [data-lenis-prevent] {
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lenis.lenis-stopped {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lenis.lenis-scrolling iframe {
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,34 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Geist, Geist_Mono } from "next/font/google";
|
import { Space_Grotesk, Outfit } from "next/font/google";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
const geistSans = Geist({
|
const spaceGrotesk = Space_Grotesk({
|
||||||
variable: "--font-geist-sans",
|
variable: "--font-space-grotesk",
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
|
weight: ["300", "400", "500", "600", "700"],
|
||||||
});
|
});
|
||||||
|
|
||||||
const geistMono = Geist_Mono({
|
const outfit = Outfit({
|
||||||
variable: "--font-geist-mono",
|
variable: "--font-outfit",
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
|
weight: ["300", "400", "500", "600", "700", "800"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Create Next App",
|
title: "SCENERJİ | Sürdürülebilir Enerji Mühendisliği & Yeşil Dönüşüm",
|
||||||
description: "Generated by create next app",
|
description: "Scenerji, dekarbonizasyon, yeşil dönüşüm destekleri ve sürdürülebilir enerji projeleri için dünya standartlarında mühendislik ve danışmanlık hizmetleri sunar.",
|
||||||
|
keywords: [
|
||||||
|
"sürdürülebilir enerji",
|
||||||
|
"yeşil dönüşüm",
|
||||||
|
"enerji mühendisliği",
|
||||||
|
"dekarbonizasyon",
|
||||||
|
"karbon ayak izi",
|
||||||
|
"enerji danışmanlığı",
|
||||||
|
"yeşil dönüşüm destekleri",
|
||||||
|
],
|
||||||
|
icons: {
|
||||||
|
icon: "/favicon.ico",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
@@ -24,10 +38,12 @@ export default function RootLayout({
|
|||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html
|
<html
|
||||||
lang="en"
|
lang="tr"
|
||||||
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
|
className={`${spaceGrotesk.variable} ${outfit.variable} h-full antialiased dark`}
|
||||||
>
|
>
|
||||||
<body className="min-h-full flex flex-col">{children}</body>
|
<body className="min-h-full flex flex-col font-outfit bg-bg-primary text-text-primary overflow-x-hidden selection:bg-accent-emerald selection:text-bg-primary">
|
||||||
|
{children}
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default function GridBackground() {
|
||||||
|
return (
|
||||||
|
<div className="absolute inset-0 w-full h-full overflow-hidden pointer-events-none z-[0]">
|
||||||
|
{/* Dynamic Ambient Glows */}
|
||||||
|
<div className="absolute top-[10%] left-[20%] w-[35vw] h-[35vw] bg-accent-emerald-dim rounded-full blur-[120px] animate-pulse-slow opacity-60" />
|
||||||
|
<div className="absolute bottom-[20%] right-[10%] w-[45vw] h-[45vw] bg-accent-cyan-dim rounded-full blur-[150px] animate-pulse-slow opacity-50" style={{ animationDelay: "2s" }} />
|
||||||
|
|
||||||
|
{/* Grid Pattern */}
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 w-full h-full"
|
||||||
|
style={{
|
||||||
|
backgroundImage: `
|
||||||
|
linear-gradient(to right, rgba(13, 242, 147, 0.03) 1px, transparent 1px),
|
||||||
|
linear-gradient(to bottom, rgba(13, 242, 147, 0.03) 1px, transparent 1px)
|
||||||
|
`,
|
||||||
|
backgroundSize: "60px 60px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Decorative vertical lines */}
|
||||||
|
<div className="absolute left-[15%] top-0 bottom-0 w-[1px] bg-gradient-to-b from-transparent via-accent-emerald/5 to-transparent" />
|
||||||
|
<div className="absolute left-[50%] top-0 bottom-0 w-[1px] bg-gradient-to-b from-transparent via-accent-cyan/5 to-transparent" />
|
||||||
|
<div className="absolute right-[15%] top-0 bottom-0 w-[1px] bg-gradient-to-b from-transparent via-accent-emerald/5 to-transparent" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, { useEffect, useRef } from "react";
|
||||||
|
import Lenis from "lenis";
|
||||||
|
|
||||||
|
export default function LenisProvider({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
const lenisRef = useRef<Lenis | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Initialize Lenis
|
||||||
|
const lenis = new Lenis({
|
||||||
|
duration: 1.2,
|
||||||
|
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
|
||||||
|
orientation: "vertical",
|
||||||
|
gestureOrientation: "vertical",
|
||||||
|
smoothWheel: true,
|
||||||
|
wheelMultiplier: 1,
|
||||||
|
touchMultiplier: 1.5,
|
||||||
|
});
|
||||||
|
|
||||||
|
lenisRef.current = lenis;
|
||||||
|
|
||||||
|
// RAF loop
|
||||||
|
function raf(time: number) {
|
||||||
|
lenis.raf(time);
|
||||||
|
requestAnimationFrame(raf);
|
||||||
|
}
|
||||||
|
|
||||||
|
requestAnimationFrame(raf);
|
||||||
|
|
||||||
|
// Bind clean-up
|
||||||
|
return () => {
|
||||||
|
lenis.destroy();
|
||||||
|
lenisRef.current = null;
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return <>{children}</>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default function NoiseOverlay() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="fixed inset-0 w-full h-full pointer-events-none z-[99999] opacity-[0.025]"
|
||||||
|
style={{
|
||||||
|
backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`,
|
||||||
|
backgroundRepeat: "repeat",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
|
|
||||||
|
const DIAGNOSTICS = [
|
||||||
|
"SOLAR PANEL DİZİLERİ SENKRONİZE EDİLİYOR...",
|
||||||
|
"RÜZGAR TRÜBİN KOMPANSATÖRLERİ DENGELENİYOR...",
|
||||||
|
"KOJENERASYON OPTİMİZASYON KATI AKTİFLEŞTİRİLİYOR...",
|
||||||
|
"YEŞİL DÖNÜŞÜM KARBON AĞI YAPILANDIRILIYOR...",
|
||||||
|
"SCENERJİ ENERJİ AKIŞI STABİL DURUMA GETİRİLDİ.",
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Preloader({ onComplete }: { onComplete: () => void }) {
|
||||||
|
const [progress, setProgress] = useState(0);
|
||||||
|
const [diagnosticText, setDiagnosticText] = useState(DIAGNOSTICS[0]);
|
||||||
|
const [isVisible, setIsVisible] = useState(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let currentProgress = 0;
|
||||||
|
const duration = 2400; // 2.4 seconds total preloader time
|
||||||
|
const intervalTime = 20;
|
||||||
|
const step = 100 / (duration / intervalTime);
|
||||||
|
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
currentProgress += step;
|
||||||
|
if (currentProgress >= 100) {
|
||||||
|
currentProgress = 100;
|
||||||
|
clearInterval(timer);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsVisible(false);
|
||||||
|
setTimeout(onComplete, 800); // Allow curtain reveal animation to complete
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
setProgress(Math.floor(currentProgress));
|
||||||
|
|
||||||
|
// Update diagnostic text based on progress
|
||||||
|
const diagIndex = Math.min(
|
||||||
|
Math.floor((currentProgress / 100) * DIAGNOSTICS.length),
|
||||||
|
DIAGNOSTICS.length - 1
|
||||||
|
);
|
||||||
|
setDiagnosticText(DIAGNOSTICS[diagIndex]);
|
||||||
|
}, intervalTime);
|
||||||
|
|
||||||
|
return () => clearInterval(timer);
|
||||||
|
}, [onComplete]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AnimatePresence>
|
||||||
|
{isVisible && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 1 }}
|
||||||
|
exit={{
|
||||||
|
clipPath: "polygon(0 0, 100% 0, 100% 0, 0 0)",
|
||||||
|
transition: { duration: 0.8, ease: [0.76, 0, 0.24, 1] }
|
||||||
|
}}
|
||||||
|
className="fixed inset-0 w-full h-full bg-[#03070b] z-[99999] flex flex-col items-center justify-center p-6 select-none"
|
||||||
|
>
|
||||||
|
{/* Subtle decorative grid in preloader */}
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 w-full h-full opacity-10 pointer-events-none"
|
||||||
|
style={{
|
||||||
|
backgroundImage: `
|
||||||
|
linear-gradient(to right, rgba(13, 242, 147, 0.05) 1px, transparent 1px),
|
||||||
|
linear-gradient(to bottom, rgba(13, 242, 147, 0.05) 1px, transparent 1px)
|
||||||
|
`,
|
||||||
|
backgroundSize: "40px 40px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="w-full max-w-xl flex flex-col relative z-10">
|
||||||
|
{/* Tech Logo / Icon */}
|
||||||
|
<div className="flex items-center gap-3 mb-10">
|
||||||
|
<div className="w-6 h-6 border border-accent-emerald flex items-center justify-center rounded-sm animate-spin-slow">
|
||||||
|
<div className="w-2.5 h-2.5 bg-accent-emerald" />
|
||||||
|
</div>
|
||||||
|
<span className="font-space text-lg font-bold tracking-[0.2em] text-accent-emerald uppercase">
|
||||||
|
SCENERJİ SYSTEM
|
||||||
|
</span>
|
||||||
|
<span className="ml-auto text-[10px] font-mono text-text-dim px-2 py-0.5 border border-text-dim/20 rounded-sm">
|
||||||
|
v2.6.0
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Diagnostic Logs */}
|
||||||
|
<div className="h-16 font-mono text-xs text-text-secondary border-l border-accent-emerald/20 pl-4 mb-8 flex flex-col justify-center">
|
||||||
|
<span className="text-[10px] text-accent-cyan tracking-wider uppercase mb-1">
|
||||||
|
[SİSTEM TEŞHİS KÜTÜPHANESİ]
|
||||||
|
</span>
|
||||||
|
<span className="animate-pulse">{diagnosticText}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Progress Counter & Bar */}
|
||||||
|
<div className="flex items-end justify-between font-space mb-3">
|
||||||
|
<span className="text-sm font-light text-text-secondary tracking-widest uppercase">
|
||||||
|
ENERJİ AĞI KALİBRASYONU
|
||||||
|
</span>
|
||||||
|
<span className="text-3xl font-bold text-accent-emerald tabular-nums">
|
||||||
|
{progress}%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full h-[2px] bg-bg-tertiary relative overflow-hidden rounded-full">
|
||||||
|
<motion.div
|
||||||
|
className="h-full bg-gradient-to-r from-accent-cyan to-accent-emerald"
|
||||||
|
style={{ width: `${progress}%` }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8 flex justify-between font-mono text-[9px] text-text-dim uppercase tracking-wider">
|
||||||
|
<span>KURULUM: AYRIS TECH</span>
|
||||||
|
<span>LOKASYON: TÜRKİYE</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,416 @@
|
|||||||
|
# Şablon Tasarım Rehberi
|
||||||
|
### Ayris Tech — Premium Demo Sistemi
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Görevin
|
||||||
|
|
||||||
|
Potansiyel müşterilere gönderilecek demo siteleri için sektöre özel Next.js şablonları yazıyorsun.
|
||||||
|
|
||||||
|
Öncelik sırası: **1. Tasarım ve his → 2. Animasyon → 3. İçerik → 4. Teknik detaylar**
|
||||||
|
|
||||||
|
Müşteri linke tıkladığında ilk 3 saniyede "bu benim için yapılmış, bu çok pahalı görünüyor" hissini yaşamalı. Kod çalışıyor mu çalışmıyor mu ikinci plandır — önce göz kamaştır.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tasarım Felsefesi
|
||||||
|
|
||||||
|
### "Oha" Anı Zorunludur
|
||||||
|
|
||||||
|
Her şablonun sayfaya girince insanı duraksatan **bir imza momenti** olmalı. Bu an tasarlanmış, hesaplanmış, sektöre özgün olmalı. Genel bir animasyon değil — o sektörün ruhunu yansıtan bir hareket.
|
||||||
|
|
||||||
|
Referans seviye: **Awwwards Site of the Day**. Hedef his: "Bu siteyi kim yaptı, nasıl yaptı?"
|
||||||
|
|
||||||
|
### Tasarım Kararlarında Öncelik Sırası
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Boşluk ve nefes — section'lar arası ritim, padding cömertliği
|
||||||
|
2. Tipografi gücü — başlıklar cesur ve büyük, hiyerarşi net
|
||||||
|
3. Fotoğraf kalitesi — her fotoğraf kompozisyon düşünülerek seçilmeli
|
||||||
|
4. Renk disiplini — max 2-3 renk, geri kalanı siyah/beyaz/gri
|
||||||
|
5. Hareket kalitesi — az animasyon ama her biri mükemmel
|
||||||
|
6. Detay titizliği — hover state'ler, geçişler, micro-interaction'lar
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nasıl Düşünmeli
|
||||||
|
|
||||||
|
Görseller verildiğinde şunu sor: **"Bu tasarımı 10.000 USD'ye satan ajans ne hissettirdi?"**
|
||||||
|
|
||||||
|
- Boşlukla mı ezdi? (luxury whitespace)
|
||||||
|
- Tipografiyle mi şok etti? (devasa başlık, küçük body)
|
||||||
|
- Fotoğrafla mı sardı? (fullscreen, parallax, overlay)
|
||||||
|
- Hareketle mi büyüledi? (curtain, reveal, magnetic)
|
||||||
|
- Detayla mı ikna etti? (custom cursor, subtle grain, line animation)
|
||||||
|
|
||||||
|
Cevap hangisi ise — oradan başla, diğerlerini o etrafına kur.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## İmza Moment Kütüphanesi
|
||||||
|
|
||||||
|
Her şablona aşağıdakilerden **en az bir** tane koy. Birden fazla koyacaksan aralarına yeterli "sessizlik" bırak.
|
||||||
|
|
||||||
|
### Sayfa Açılışı
|
||||||
|
- **Curtain reveal** — siyah ekran ortadan ikiye ayrılır, fotoğraf ortaya çıkar
|
||||||
|
- **Preloader çizgi** — ince bir çizgi soldan sağa ilerler, logo belirir, sahne açılır
|
||||||
|
- **Staggered text entrance** — başlık kelime kelime veya karakter karakter düşer
|
||||||
|
- **Scale-up reveal** — küçük merkezi bir görsel tam ekrana açılır
|
||||||
|
|
||||||
|
### Scroll Animasyonları
|
||||||
|
- **Parallax hero** — scroll ettikçe fotoğraf daha yavaş iner, metin daha hızlı çıkar
|
||||||
|
- **Sticky + akan metin** — fotoğraf sabit kalır, metin onun üzerinden akar
|
||||||
|
- **Horizontal scroll bölüm** — kartlar/menü yatay ilerler, mouse/touch ile sürüklenir
|
||||||
|
- **Pinned section** — section scroll boyunca sabit kalır, içeriği değişir (tablar gibi)
|
||||||
|
- **Text scale on scroll** — başlık küçükten büyüğe veya büyükten küçüğe dönüşür
|
||||||
|
|
||||||
|
### Hover & Mikro
|
||||||
|
- **Magnetic buton** — mouse yaklaştıkça buton sana doğru çekilir
|
||||||
|
- **Custom cursor** — varsayılan cursor kaybolur, markaya özgü daire/metin gelir
|
||||||
|
- **Image tilt** — kart hover'ında 3D perspektif eğimi (rotateX/Y)
|
||||||
|
- **Clip-path reveal** — fotoğraf hover'da yukarıdan aşağı açılır
|
||||||
|
- **Underline draw** — link hover'ında çizgi soldan sağa çizilir
|
||||||
|
|
||||||
|
### Atmosfer
|
||||||
|
- **Scrolling marquee** — sonsuz döngü metin bandı (iki yönde farklı hızda olursa daha iyi)
|
||||||
|
- **Grain texture overlay** — tüm sayfa üstünde ince film grain (opacity 0.03-0.06)
|
||||||
|
- **Ambient glow** — arka planda renk blobları yavaşça hareket eder
|
||||||
|
- **Video loop** — hero'da sessiz, döngü video (restoran, otel için)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tipografi Kuralları
|
||||||
|
|
||||||
|
Pahalı hissinin %40'ı tipografiden gelir.
|
||||||
|
|
||||||
|
```
|
||||||
|
Başlık boyutu: clamp(48px, 8vw, 120px) — küçük ekranda küçülür, büyük ekranda büyür
|
||||||
|
Body boyutu: 16px minimum, 18px ideal
|
||||||
|
Satır yüksekliği: başlıklarda 0.9-1.0, body'de 1.6-1.8
|
||||||
|
Harf aralığı: büyük harf başlıklarda tracking-widest, serif başlıklarda -0.02em
|
||||||
|
```
|
||||||
|
|
||||||
|
**Font kombinasyonları (sektöre göre):**
|
||||||
|
- Otel/Butik/Restoran → Playfair Display (serif) + Inter (sans) — klasik lüks
|
||||||
|
- Mimari/Kurumsal → Inter Black + Inter Regular — modern güç
|
||||||
|
- Bar/Gastro → Cormorant Garamond + Space Grotesk — sofistike
|
||||||
|
- Klinik/SaaS → DM Sans veya Sora + monospace detay — temiz güven
|
||||||
|
|
||||||
|
Başlık tek satırda yoksa **satır kırılmalarını elle kontrol et** — otomatik kırılma çirkin görünür.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Renk ve Atmosfer Kuralları
|
||||||
|
|
||||||
|
### Koyu Tema (restoran, bar, otel, gastro)
|
||||||
|
- Arka plan: `#080810` veya `#0a0a0a` — tam siyah değil, hafif tonlu
|
||||||
|
- Metin: `#ffffff` + `rgba(255,255,255,0.5)` ikincil
|
||||||
|
- Aksant: firmanın ana rengi — sadece CTA, badge, vurgu için
|
||||||
|
- Fotoğraflar üstünde: `rgba(0,0,0,0.3-0.5)` overlay — direkt koymadan
|
||||||
|
|
||||||
|
### Açık Tema (klinik, mimari, kurumsal, butik)
|
||||||
|
- Arka plan: `#ffffff` veya `#f8f7f4` (hafif warm) veya `#f5f0e8` (krem)
|
||||||
|
- Metin: `#0a0a0a` veya `#1a1a1a`
|
||||||
|
- Aksant: firmanın ana rengi
|
||||||
|
- İkincil yüzeyler: `#f0f0f0` veya `rgba(0,0,0,0.04)`
|
||||||
|
|
||||||
|
### Renk Disiplini
|
||||||
|
- Ana renk: butonlar, başlık vurgusu, badge, aktif state
|
||||||
|
- İkincil renk: hover state, border, gradient ikinci noktası
|
||||||
|
- Nötr: arka planlar, kartlar, ayırıcılar
|
||||||
|
- **Başka renk yok.** Emoji veya ikonlar nötr tutulur.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fotoğraf Kullanımı
|
||||||
|
|
||||||
|
Fotoğraflar kod kadar önemli. Kötü fotoğraf iyi tasarımı mahveder.
|
||||||
|
|
||||||
|
**Unsplash koleksiyonları (sektöre göre):**
|
||||||
|
- Otel/Resort: `https://source.unsplash.com/1920x1080/?luxury,hotel,resort`
|
||||||
|
- Restoran: `https://source.unsplash.com/1920x1080/?restaurant,food,gastronomy`
|
||||||
|
- Bar: `https://source.unsplash.com/1920x1080/?cocktail,bar,dark`
|
||||||
|
- Mimari: `https://source.unsplash.com/1920x1080/?architecture,interior,modern`
|
||||||
|
- Klinik: `https://source.unsplash.com/1920x1080/?clinic,medical,clean`
|
||||||
|
|
||||||
|
**Kurallar:**
|
||||||
|
- Hero fotoğrafı her zaman `object-cover` + `object-position: center`
|
||||||
|
- Dikey fotoğraflar (portrait) kart içinde daha dramatik görünür — kullan
|
||||||
|
- Birden fazla fotoğraf varsa renk tonu tutarlı olsun (hepsi sıcak veya hepsi soğuk)
|
||||||
|
- `picsum.photos` sadece hızlı test için — final görünümde Unsplash parametreli URL kullan
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Animasyon Kalitesi
|
||||||
|
|
||||||
|
### Easing Değerleri
|
||||||
|
```typescript
|
||||||
|
// Smooth deceleration — genel kullanım
|
||||||
|
ease: [0.25, 0.46, 0.45, 0.94] as [number,number,number,number]
|
||||||
|
|
||||||
|
// Dramatic entrance — hero başlıklar
|
||||||
|
ease: [0.16, 1, 0.3, 1] as [number,number,number,number]
|
||||||
|
|
||||||
|
// Snappy — buton, badge, küçük elementler
|
||||||
|
ease: [0.34, 1.56, 0.64, 1] as [number,number,number,number]
|
||||||
|
|
||||||
|
// Linear — marquee, döngüler
|
||||||
|
ease: "linear"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Süre Kuralları
|
||||||
|
```
|
||||||
|
Micro (hover, badge): 0.15-0.25s
|
||||||
|
Element entrance: 0.6-0.8s
|
||||||
|
Section transition: 0.8-1.0s
|
||||||
|
Page reveal / curtain: 1.0-1.4s
|
||||||
|
Marquee döngü: 20-40s (içerik uzunluğuna göre)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stagger Ritmi
|
||||||
|
```typescript
|
||||||
|
// Çocuk sayısına göre stagger ayarla
|
||||||
|
3-4 element: staggerChildren: 0.15
|
||||||
|
5-8 element: staggerChildren: 0.08
|
||||||
|
9+ element: staggerChildren: 0.05
|
||||||
|
```
|
||||||
|
|
||||||
|
### Animasyon Monotonluğu Kırma
|
||||||
|
Her section aynı `fadeUp` ile başlarsa sayfa uyutur. Karıştır:
|
||||||
|
- Hero: curtain veya scale reveal
|
||||||
|
- Stats: sayaç animasyonu (AnimatedCounter)
|
||||||
|
- Kartlar: stagger + hafif x offset (soldan veya sağdan)
|
||||||
|
- Galeri: clip-path veya opacity-only (y hareketi olmadan)
|
||||||
|
- CTA section: parallax arka plan + metin fade
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Lenis Smooth Scroll Kurulumu
|
||||||
|
|
||||||
|
Her şablona ekle:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
"use client";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
// Component içinde:
|
||||||
|
useEffect(() => {
|
||||||
|
let lenis: any;
|
||||||
|
import("@studio-freight/lenis").then(({ default: Lenis }) => {
|
||||||
|
lenis = new Lenis({ duration: 1.2, easing: (t: number) => Math.min(1, 1.001 - Math.pow(2, -10 * t)) });
|
||||||
|
function raf(time: number) { lenis.raf(time); requestAnimationFrame(raf); }
|
||||||
|
requestAnimationFrame(raf);
|
||||||
|
});
|
||||||
|
return () => lenis?.destroy();
|
||||||
|
}, []);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Section Tasarım Standartları
|
||||||
|
|
||||||
|
### Hero
|
||||||
|
- Her zaman viewport yüksekliği: `min-h-screen`
|
||||||
|
- Fotoğraf varsa: `position: absolute, inset: 0, object-fit: cover` + koyu overlay
|
||||||
|
- Başlık: clamp ile responsive, viewport'un %60-70'ini kaplamalı
|
||||||
|
- CTA buton: tek, net, aksant renkli — ikinci buton varsa ghost/outline
|
||||||
|
|
||||||
|
### Marquee Bandı (opsiyonel ama etkili)
|
||||||
|
Hero ile sonraki section arasına koy. İki yönde farklı iki satır daha güçlü görünür.
|
||||||
|
|
||||||
|
### İki Kolonlu (Split) Section
|
||||||
|
```
|
||||||
|
Sol: metin + CTA Sağ: tall fotoğraf (aspect-ratio: 3/4)
|
||||||
|
Metin sola hizalı Fotoğraf slight overlap (negatif margin)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kart Grid'leri
|
||||||
|
- 3'lü grid: her kart eşit, hover'da `y: -8` ve border glow
|
||||||
|
- Masonry: sadece galeri için — CSS columns veya css-grid ile
|
||||||
|
- Horizontal scroll: `overflow-x: auto`, `scrollbar-width: none`, touch-action: pan-x
|
||||||
|
|
||||||
|
### CTA Section (Son Bölüm)
|
||||||
|
En az bir kez tam genişlikte, fotoğraf arka planlı olsun. Başlık büyük, CTA tek.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"zorunlu": [
|
||||||
|
"Next.js 14 App Router",
|
||||||
|
"Framer Motion v11",
|
||||||
|
"Tailwind CSS v3",
|
||||||
|
"TypeScript strict",
|
||||||
|
"@studio-freight/lenis"
|
||||||
|
],
|
||||||
|
"gerektiğinde": [
|
||||||
|
"Three.js / @react-three/fiber (sadece ambient bg için, performans dikkat)",
|
||||||
|
"react-lottie-player (loading, boş state ikonları için)",
|
||||||
|
"usehooks-ts (useWindowSize, useIntersectionObserver)"
|
||||||
|
],
|
||||||
|
"yasak": [
|
||||||
|
"jQuery",
|
||||||
|
"Bootstrap",
|
||||||
|
"CSS @keyframes animasyonları (Framer Motion kullan)",
|
||||||
|
"inline style ile animasyon (transform, opacity — Framer Motion kullan)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Framer Motion zorunlu kurallar:**
|
||||||
|
- `ease` array'leri her zaman type assertion: `as [number,number,number,number]`
|
||||||
|
- Scroll animasyonları: `useScroll` + `useTransform`
|
||||||
|
- Section girişleri: `whileInView` + `viewport={{ once: true }}`
|
||||||
|
- Layout animasyonları: `layout` prop — yükseklik değişimlerinde kullan
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kalite Kontrol Listesi
|
||||||
|
|
||||||
|
Kodu teslim etmeden önce şunları kontrol et:
|
||||||
|
|
||||||
|
**Tasarım:**
|
||||||
|
- [ ] Sayfaya girince ilk 3 saniyede "oha" dedirten bir şey var mı?
|
||||||
|
- [ ] Boşluklar cömert mi — hiçbir element birbirine yapışık değil mi?
|
||||||
|
- [ ] Başlıklar yeterince büyük mü — yarım metre uzaktan okunabilir mi?
|
||||||
|
- [ ] Renk disiplini korunuyor mu — max 3 renk var mı?
|
||||||
|
- [ ] Fotoğraflar kompozisyon olarak uygun mu?
|
||||||
|
|
||||||
|
**Animasyon:**
|
||||||
|
- [ ] Her section farklı animasyon mu kullanıyor (monotonluk yok)?
|
||||||
|
- [ ] Easing değerleri sert mi yoksa yumuşak mı? (Sert olmamalı)
|
||||||
|
- [ ] Lenis smooth scroll çalışıyor mu?
|
||||||
|
- [ ] Hover state'lerin hepsi var mı?
|
||||||
|
|
||||||
|
**Detay:**
|
||||||
|
- [ ] Demo banner sabit mi: `"Bu site demo amaçlıdır — demo.ayristech.com"`
|
||||||
|
- [ ] Mobile'da layout bozulmuyor mu?
|
||||||
|
- [ ] TypeScript hataları var mı (`any` yok)?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Proje Yapısı
|
||||||
|
|
||||||
|
```
|
||||||
|
demo-ayristech/
|
||||||
|
├── app/
|
||||||
|
│ ├── page.tsx # Showcase index
|
||||||
|
│ └── [slug]/page.tsx # Dynamic routing
|
||||||
|
├── components/
|
||||||
|
│ └── templates/
|
||||||
|
│ └── [SektörTemplate]/
|
||||||
|
│ └── index.tsx # Her şablon kendi klasöründe
|
||||||
|
├── data/
|
||||||
|
│ └── demos.ts # Tüm demo verisi
|
||||||
|
└── components/ui/
|
||||||
|
└── AnimatedCounter.tsx # Scroll-triggered sayaç
|
||||||
|
```
|
||||||
|
|
||||||
|
Yeni şablon eklerken:
|
||||||
|
1. `components/templates/YeniTemplate/index.tsx` oluştur
|
||||||
|
2. `data/demos.ts` interface'ine yeni sektör tipini ve alanları ekle
|
||||||
|
3. `app/[slug]/page.tsx` routing'e `if (data.template === "yeni") return <YeniTemplate data={data} />;`
|
||||||
|
4. `app/page.tsx` `templateLabels`'a yeni badge ekle
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Müşteri Sitesi SS Analizi
|
||||||
|
|
||||||
|
Sana müşterinin mevcut sitesinin ekran görüntüleri verildiğinde şu sırayla ilerle:
|
||||||
|
|
||||||
|
### 1. İçerik Çıkarımı
|
||||||
|
|
||||||
|
Her SS'den şunları çıkar:
|
||||||
|
|
||||||
|
| Alan | Nereden Bulunur |
|
||||||
|
|---|---|
|
||||||
|
| Firma adı | Header, logo yanı, title |
|
||||||
|
| Slogan | Hero başlığı veya alt metin |
|
||||||
|
| Şehir / Adres | Footer, iletişim sayfası |
|
||||||
|
| Telefon | Header, footer, iletişim |
|
||||||
|
| E-posta | Footer, iletişim sayfası |
|
||||||
|
| Çalışma saatleri | Footer veya iletişim |
|
||||||
|
| Hizmetler | Hizmetler/servisler/poliklinikler sayfası |
|
||||||
|
| Ekip / Doktorlar | Kadro/hakkımızda sayfası |
|
||||||
|
| Yorumlar / Referanslar | Varsa ana sayfa veya ayrı sayfa |
|
||||||
|
| Sosyal medya | Footer veya header ikonları |
|
||||||
|
|
||||||
|
### 2. Mevcut Tasarımı Değerlendir
|
||||||
|
|
||||||
|
SS'lere bakarak kısaca not al:
|
||||||
|
- **Renk paleti:** Mevcut ana renk nedir?
|
||||||
|
- **Genel his:** Profesyonel mi, eski mi, amatör mü?
|
||||||
|
- **Eksikler:** Animasyon yok, mobile bozuk, fotoğraf kalitesi kötü vb.
|
||||||
|
- **Güçlü yanlar:** Korunabilecek bir şey var mı?
|
||||||
|
|
||||||
|
Bu değerlendirmeyi şablona yansıt — mevcut siteyi taklit etme, **dönüştür**.
|
||||||
|
|
||||||
|
### 3. demos.ts Formatında Çıkar
|
||||||
|
|
||||||
|
Analiz sonucunu aşağıdaki formatta hazırla, eksik alanları makul şekilde doldur:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
slug: "firma-adi", // firma adından türet, küçük harf, tire ile
|
||||||
|
template: "klinik", // sektöre göre seç
|
||||||
|
firma: {
|
||||||
|
adi: "Firma Adı",
|
||||||
|
slogan: "SS'den alınan slogan veya uygun bir slogan üret",
|
||||||
|
sehir: "Şehir",
|
||||||
|
adres: "Tam adres",
|
||||||
|
telefon: "+90 ...",
|
||||||
|
email: "info@...",
|
||||||
|
logoEmoji: "🏥", // sektöre uygun emoji
|
||||||
|
renkAna: "#______", // mevcut sitenin ana rengi
|
||||||
|
renkKoyu: "#______", // daha koyu tonu
|
||||||
|
renkAcik: "#______", // çok açık tonu (bg için)
|
||||||
|
},
|
||||||
|
istatistikler: [
|
||||||
|
{ deger: "15+", etiket: "Yıllık Deneyim" },
|
||||||
|
// SS'de rakam varsa al, yoksa sektöre uygun üret
|
||||||
|
],
|
||||||
|
hizmetler: [
|
||||||
|
{ ikon: "🔬", baslik: "Hizmet Adı", aciklama: "Kısa açıklama" },
|
||||||
|
// SS'deki hizmetler sayfasından çek
|
||||||
|
],
|
||||||
|
yorumlar: [
|
||||||
|
{ yazar: "Ad Soyad", yorum: "...", puan: 5, tarih: "2024", emoji: "👤" },
|
||||||
|
// SS'de yoksa 3 adet gerçekçi yorum üret
|
||||||
|
],
|
||||||
|
// Sektöre özel alanlar — SS'den çek, yoksa üret
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Şablon Seçimi
|
||||||
|
|
||||||
|
Sektöre göre hangi şablonun kullanılacağına karar ver:
|
||||||
|
|
||||||
|
| Sektör | Şablon |
|
||||||
|
|---|---|
|
||||||
|
| Klinik, hastane, sağlık merkezi | `klinik` |
|
||||||
|
| Diş kliniği, estetik | `dental` |
|
||||||
|
| Restoran, kafe, bistro | `restoran` veya `restoran2` |
|
||||||
|
| Bar, meyhane, gece kulübü | `bar` veya `bar2` |
|
||||||
|
| Otel, resort, apart | `hotel1`, `hotel2` veya `hotel3` |
|
||||||
|
| Taksi, transfer, ulaşım | `taxi` veya `taxi2` |
|
||||||
|
| Yazılım, SaaS, chatbot | `chatbot` |
|
||||||
|
| İnşaat, mimarlık, kurumsal | `kurumsal` |
|
||||||
|
|
||||||
|
Mevcut şablonlardan hiçbiri uygun değilse: **yeni şablon yaz** — TEMPLATE_BRIEF'teki tasarım kurallarına uyarak.
|
||||||
|
|
||||||
|
### 5. Antigravity'e Ver
|
||||||
|
|
||||||
|
Analiz tamamlandığında şunu söyle:
|
||||||
|
|
||||||
|
> "Bu `demos.ts` verisini kullan. TEMPLATE_BRIEF.md'deki kurallara göre `[ŞabonAdı]` şablonunu yaz. Mevcut sitenin renk paletini koru ama tasarımı tamamen modernize et. İmza moment olarak `[seçilen imza moment]` kullan."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Son Not
|
||||||
|
|
||||||
|
Amaç: müşteriye link atıp "bak, senin için yaptım" diyebilmek.
|
||||||
|
|
||||||
|
**Standart değil, özel. Güzel değil, etkileyici. Çalışıyor değil, hissettiriyor.**
|
||||||
|
|
||||||
|
Eğer şablona baktığında "bu idare eder" diyorsan — yeniden başla.
|
||||||
|
After Width: | Height: | Size: 295 KiB |
|
After Width: | Height: | Size: 317 KiB |
|
After Width: | Height: | Size: 213 KiB |
|
After Width: | Height: | Size: 295 KiB |
|
After Width: | Height: | Size: 279 KiB |
|
After Width: | Height: | Size: 515 KiB |
|
After Width: | Height: | Size: 277 KiB |
|
After Width: | Height: | Size: 225 KiB |
|
After Width: | Height: | Size: 331 KiB |
|
After Width: | Height: | Size: 120 KiB |
@@ -1,7 +1,7 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
/* config options here */
|
output: "standalone",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
"name": "scenerji",
|
"name": "scenerji",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"framer-motion": "^12.40.0",
|
||||||
|
"lenis": "^1.3.23",
|
||||||
|
"lucide-react": "^1.17.0",
|
||||||
"next": "16.2.6",
|
"next": "16.2.6",
|
||||||
"react": "19.2.4",
|
"react": "19.2.4",
|
||||||
"react-dom": "19.2.4"
|
"react-dom": "19.2.4"
|
||||||
@@ -3762,6 +3765,33 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/framer-motion": {
|
||||||
|
"version": "12.40.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.40.0.tgz",
|
||||||
|
"integrity": "sha512-uaBd3qC1v3KQqBEjwTUd183K6PbS+j0yR9w9VmEOLWA/tnUcSn8Xa3uck7t4dgpDoUss8xQTcj8W2L07lrnLFg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-dom": "^12.40.0",
|
||||||
|
"motion-utils": "^12.39.0",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/function-bind": {
|
"node_modules/function-bind": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
@@ -4689,6 +4719,37 @@
|
|||||||
"node": ">=0.10"
|
"node": ">=0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lenis": {
|
||||||
|
"version": "1.3.23",
|
||||||
|
"resolved": "https://registry.npmjs.org/lenis/-/lenis-1.3.23.tgz",
|
||||||
|
"integrity": "sha512-YxYq3TJqj9sJNv0V9SkyQHejt14xwyIwgDaaMK89Uf9SxQfIszu+gTQSSphh6BWlLTNVKvvXAGkg+Zf+oFIevg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"workspaces": [
|
||||||
|
"packages/*",
|
||||||
|
"playground",
|
||||||
|
"playground/*"
|
||||||
|
],
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/darkroomengineering"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@nuxt/kit": ">=3.0.0",
|
||||||
|
"react": ">=17.0.0",
|
||||||
|
"vue": ">=3.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@nuxt/kit": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"vue": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/levn": {
|
"node_modules/levn": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
||||||
@@ -5022,6 +5083,15 @@
|
|||||||
"yallist": "^3.0.2"
|
"yallist": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lucide-react": {
|
||||||
|
"version": "1.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.17.0.tgz",
|
||||||
|
"integrity": "sha512-9FA9evdox/JQL5PT57fdA1x/yg8T7knJ98+zjTL3UfKza6pflQUUh3XtaQIHKvnsJw1lmsEyHVlt5jchYxOQ5w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.21",
|
"version": "0.30.21",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||||
@@ -5089,6 +5159,21 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/motion-dom": {
|
||||||
|
"version": "12.40.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.40.0.tgz",
|
||||||
|
"integrity": "sha512-HxU3ZaBwNPVQUBQf1xxgq+7JrPNZvjLVxgbpEZL7RrWJnsxOf0/OM+yrHG9ogLQ31Do/r57Oz2gQWPK+6q62mg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-utils": "^12.39.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-utils": {
|
||||||
|
"version": "12.39.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.39.0.tgz",
|
||||||
|
"integrity": "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
"lint": "eslint"
|
"lint": "eslint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"framer-motion": "^12.40.0",
|
||||||
|
"lenis": "^1.3.23",
|
||||||
|
"lucide-react": "^1.17.0",
|
||||||
"next": "16.2.6",
|
"next": "16.2.6",
|
||||||
"react": "19.2.4",
|
"react": "19.2.4",
|
||||||
"react-dom": "19.2.4"
|
"react-dom": "19.2.4"
|
||||||
|
|||||||