-
-
- Nicola Leone Ciardi
-
-
- Co-Founder & CEO
+ {/* People Behind CiMa - Lazy loaded */}
+
+
+
+
+ people behind cima
+
+
+
+ {/* Nicola Leone Ciardi */}
+
+
+
+
+ Nicola Leone Ciardi
+
+
+ Co-Founder & CEO
+
+
+
+ Management and computer science.
+
-
- Management and computer science.
-
-
+
+ {/* Valentina Madaudo */}
+
+
+
+
+ Valentina Madaudo
+
+
+ Co-Founder & CFO
+
+
+
+ Jr Engineer & economist for sustainable development.
+
+
-
- {/* Valentina Madaudo */}
-
-
-
-
- Valentina Madaudo
-
-
- Co-Founder & CFO
-
-
-
- Jr Engineer & economist for sustainable development.
-
-
-
-
-
-
+
+
);
}
diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css
index b18559d..a6d6c56 100644
--- a/frontend/src/app/globals.css
+++ b/frontend/src/app/globals.css
@@ -54,3 +54,60 @@ body {
line-height: 0.9;
letter-spacing: -0.04em;
}
+
+/* Performance optimizations */
+img {
+ decoding: async;
+}
+
+/* Skeleton wave animation */
+@keyframes wave {
+ 0% {
+ background-position: -1000px 0;
+ }
+ 100% {
+ background-position: 1000px 0;
+ }
+}
+
+.skeleton-wave {
+ background: linear-gradient(
+ 90deg,
+ var(--color-surface-container) 0%,
+ var(--color-surface-container-high) 50%,
+ var(--color-surface-container) 100%
+ );
+ background-size: 200% 100%;
+ animation: wave 2s infinite;
+}
+
+
+
+/* Optimize font loading */
+@font-face {
+ font-family: "Inter";
+ font-display: swap;
+ src: url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;900");
+}
+
+/* Prevent layout shift for lazy-loaded images */
+img {
+ aspect-ratio: auto;
+}
+
+/* Optimize animations for reduced motion preference */
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+
+ .skeleton-wave {
+ animation: none;
+ background: var(--color-surface-container-high);
+ }
+}
diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx
index cb2135f..81ad3dd 100644
--- a/frontend/src/app/layout.tsx
+++ b/frontend/src/app/layout.tsx
@@ -37,10 +37,34 @@ export default function RootLayout({
return (
+ {/* Preconnect to Google Fonts for faster loading */}
+
+
+
+ {/* DNS prefetch for third-party domains */}
+
+
+ {/* Material Symbols with swap for faster first paint */}
+
+ {/* Preload critical fonts */}
+
+
+ {/* Optimize LCP by reducing render-blocking resources */}
+
diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx
index aa4cd16..c8c8cbf 100644
--- a/frontend/src/app/page.tsx
+++ b/frontend/src/app/page.tsx
@@ -1,10 +1,53 @@
import Image from "next/image";
import Link from "next/link";
+import dynamic from "next/dynamic";
+import { Suspense } from "react";
+import { LazySection } from "@/components/LazySection";
+import { Skeleton, SkeletonWave } from "@/components/Skeleton";
+
+const ServicesSection = dynamic(
+ () => import("@/components/sections/ServicesSection"),
+ {
+ loading: () => (
+
+
+
+
+ {Array.from({ length: 5 }).map((_, i) => (
+
+
+
+
+
+ ))}
+
+
+
+ ),
+ }
+);
+
+const AboutSection = dynamic(
+ () => import("@/components/sections/AboutSection"),
+ {
+ loading: () => (
+
+ ),
+ }
+);
export default function Home() {
return (
<>
- {/* Hero Section */}
+ {/* Hero Section - Priority render for LCP */}
@@ -32,7 +75,10 @@ export default function Home() {
{/* Approccio / Ecosistema Integrato */}
-
+
@@ -44,201 +90,105 @@ export default function Home() {
- Non software isolati, ma infrastrutture digitali portanti. Ogni componente dialoga con gli altri per creare un sistema unico, costruito attorno al vostro modo di lavorare.
+ Non software isolati, ma infrastrutture digitali portanti. Ogni
+ componente dialoga con gli altri per creare un sistema unico,
+ costruito attorno al vostro modo di lavorare.
- {/* Problema / Valore */}
-
-
-
-
- architecture
-
-
Prima
-
- {[
- "Dati sparsi ovunque",
- "Processi manuali e lenti",
- "Sistemi vulnerabili",
- "Zero visibilità strategica",
- ].map((item) => (
-
-
- {item}
-
- ))}
-
-
-
-
- domain
-
-
Dopo
-
- {[
- "Un unico flusso di dati",
- "Automazione dove serve",
- "Sicurezza di livello enterprise",
- "Dashboard per decidere in tempo reale",
- ].map((item) => (
-
-
- {item}
-
- ))}
-
-
-
-
-
- {/* Servizi */}
-
-
-
-
-
- Cosa Facciamo
-
-
-
- Soluzioni su misura per il vostro metodo di lavoro. Automazione, gestione dati e competenze umane in un unico flusso.
-
+ {/* Problema / Valore - Lazy loaded */}
+
+
+
+
+
+ architecture
+
+
Prima
+
+ {[
+ "Dati sparsi ovunque",
+ "Processi manuali e lenti",
+ "Sistemi vulnerabili",
+ "Zero visibilità strategica",
+ ].map((item) => (
+
+
+ {item}
+
+ ))}
+
+
+
+
+ domain
+
+
Dopo
+
+ {[
+ "Un unico flusso di dati",
+ "Automazione dove serve",
+ "Sicurezza di livello enterprise",
+ "Dashboard per decidere in tempo reale",
+ ].map((item) => (
+
+
+ {item}
+
+ ))}
+
+
+
-
- {/* Portali */}
-
-
- hub
-
-
- Portali & Infrastrutture Digitali
-
-
- Siti, portali e web app costruiti per funzionare e crescere con voi.
-
-
+ {/* Servizi - Lazy loaded with dynamic import */}
+
+
+
+
+
- {/* Database */}
-
-
- schema
-
-
- Database & Sistemi Gestionali
-
-
- I vostri dati organizzati, accessibili e pronti per le decisioni che contano.
-
-
+ {/* Chi Siamo - Lazy loaded with dynamic import */}
+
+
+
+
+
- {/* E-commerce */}
-
-
- shopping_bag
-
-
- E-commerce & Piattaforme
-
-
- Vendita online integrata con la vostra logistica, pronta a scalare.
-
-
-
- {/* Automazioni & IA */}
-
-
-
- Automazioni & IA
-
-
- Meno lavoro ripetitivo, più tempo per quello che conta.
-
- IA anche in locale, i vostri dati restano vostri.
-
-
-
- memory
-
-
-
- {/* Cybersicurezza */}
-
-
-
- Cybersicurezza
-
-
- Protezione proattiva e monitoraggio continuo dei vostri asset digitali.
-
-
-
- verified_user
-
-
-
-
-
-
- {/* Chi Siamo */}
-
-
-
-
-
- Chi Siamo
+ {/* Filosofia - Lazy loaded */}
+
+
+
+
+ La nostra idea
-
- CiMa Progetti unisce architettura e software engineering. Costruiamo sistemi digitali solidi e scalabili per aziende che non accettano compromessi.
+
+ “La forma segue la funzione. La struttura la rende
+ duratura.”
+
+
+ Solido come cemento armato, fluido come un open-space. Zero
+ fronzoli, massima efficienza.
-
-
-
AI Expert
-
- Nicola Leone Ciardi
-
-
-
-
Jr Engineer
-
- Valentina Madaudo
-
-
-
-
-
-
- {/* Filosofia */}
-
-
-
- La nostra idea
-
-
- “La forma segue la funzione. La struttura la rende duratura.”
-
-
- Solido come cemento armato, fluido come un open-space. Zero fronzoli, massima efficienza.
-
-
-
+
+
{/* CTA / Conversione */}
-
+
@@ -258,11 +208,46 @@ export default function Home() {
preserveAspectRatio="none"
viewBox="0 0 100 100"
>
-
-
-
-
-
+
+
+
+
+
diff --git a/frontend/src/components/LazySection.tsx b/frontend/src/components/LazySection.tsx
new file mode 100644
index 0000000..5c4b5f8
--- /dev/null
+++ b/frontend/src/components/LazySection.tsx
@@ -0,0 +1,45 @@
+"use client";
+
+import React from "react";
+import { useIntersectionObserver } from "./hooks/useIntersectionObserver";
+import { SkeletonWave } from "./Skeleton";
+
+interface LazySectionProps {
+ children: React.ReactNode;
+ skeleton?: React.ReactNode;
+ className?: string;
+ skeletonHeight?: string;
+ skeletonCount?: number;
+ threshold?: number;
+ rootMargin?: string;
+}
+
+export const LazySection: React.FC
= ({
+ children,
+ skeleton,
+ className = "",
+ skeletonHeight = "100px",
+ skeletonCount = 3,
+ threshold = 0.1,
+ rootMargin = "50px",
+}) => {
+ const [ref, isVisible] = useIntersectionObserver({
+ threshold,
+ rootMargin,
+ triggerOnce: true,
+ });
+
+ const defaultSkeleton = (
+
+ {Array.from({ length: skeletonCount }).map((_, i) => (
+
+ ))}
+
+ );
+
+ return (
+
+ {!isVisible ? skeleton || defaultSkeleton : children}
+
+ );
+};
diff --git a/frontend/src/components/OptimizedImage.tsx b/frontend/src/components/OptimizedImage.tsx
new file mode 100644
index 0000000..4782133
--- /dev/null
+++ b/frontend/src/components/OptimizedImage.tsx
@@ -0,0 +1,74 @@
+"use client";
+
+import Image from "next/image";
+import React, { useState } from "react";
+import { useIntersectionObserver } from "./hooks/useIntersectionObserver";
+import { SkeletonWave } from "./Skeleton";
+
+interface OptimizedImageProps {
+ src: string;
+ alt: string;
+ width: number;
+ height: number;
+ priority?: boolean;
+ className?: string;
+ objectFit?: "contain" | "cover" | "fill" | "scale-down";
+ lazy?: boolean;
+}
+
+export const OptimizedImage: React.FC = ({
+ src,
+ alt,
+ width,
+ height,
+ priority = false,
+ className = "",
+ objectFit = "cover",
+ lazy = true,
+}) => {
+ const [isLoaded, setIsLoaded] = useState(false);
+ const [ref, isVisible] = useIntersectionObserver({
+ threshold: 0.1,
+ rootMargin: "50px",
+ });
+
+ if (!lazy || priority) {
+ return (
+ setIsLoaded(true)}
+ />
+ );
+ }
+
+ return (
+
+ {!isVisible ? (
+
+ ) : (
+ <>
+ {!isLoaded && (
+
+
+
+ )}
+
setIsLoaded(true)}
+ />
+ >
+ )}
+
+ );
+};
diff --git a/frontend/src/components/Skeleton.tsx b/frontend/src/components/Skeleton.tsx
new file mode 100644
index 0000000..ec4c4f3
--- /dev/null
+++ b/frontend/src/components/Skeleton.tsx
@@ -0,0 +1,109 @@
+"use client";
+
+import React from "react";
+
+interface SkeletonProps {
+ width?: string | number;
+ height?: string | number;
+ className?: string;
+ variant?: "text" | "heading" | "rect" | "circle";
+ count?: number;
+}
+
+export const Skeleton: React.FC = ({
+ width = "100%",
+ height = "1rem",
+ className = "",
+ variant = "rect",
+ count = 1,
+}) => {
+ const skeletons = Array.from({ length: count });
+
+ const baseStyles =
+ "animate-pulse bg-gradient-to-r from-surface-container via-surface-container-high to-surface-container";
+
+ const variantStyles: Record = {
+ text: "rounded h-4",
+ heading: "rounded h-12 w-full mb-4",
+ rect: "rounded",
+ circle: "rounded-full",
+ };
+
+ const styles = `${baseStyles} ${variantStyles[variant]} ${className}`;
+
+ return (
+ <>
+ {skeletons.map((_, i) => (
+
+ ))}
+ >
+ );
+};
+
+interface SkeletonWaveProps {
+ width?: string | number;
+ height?: string | number;
+ className?: string;
+}
+
+export const SkeletonWave: React.FC = ({
+ width = "100%",
+ height = "1rem",
+ className = "",
+}) => {
+ return (
+
+ {/* Wave animation using linear-gradient */}
+
+
+
+ );
+};
+
+interface SkeletonContainerProps {
+ isLoading: boolean;
+ children: React.ReactNode;
+ skeleton?: React.ReactNode;
+ className?: string;
+}
+
+export const SkeletonContainer: React.FC = ({
+ isLoading,
+ children,
+ skeleton,
+ className = "",
+}) => {
+ if (isLoading) {
+ return {skeleton}
;
+ }
+
+ return {children}
;
+};
diff --git a/frontend/src/components/hooks/useIntersectionObserver.ts b/frontend/src/components/hooks/useIntersectionObserver.ts
new file mode 100644
index 0000000..671e45e
--- /dev/null
+++ b/frontend/src/components/hooks/useIntersectionObserver.ts
@@ -0,0 +1,108 @@
+"use client";
+
+import { useEffect, useRef, useState } from "react";
+
+interface UseIntersectionObserverOptions {
+ threshold?: number | number[];
+ rootMargin?: string;
+ triggerOnce?: boolean;
+}
+
+export const useIntersectionObserver = (
+ options: UseIntersectionObserverOptions = {}
+): [React.RefObject, boolean] => {
+ const ref = useRef(null);
+ const [isVisible, setIsVisible] = useState(false);
+ const [hasTriggered, setHasTriggered] = useState(false);
+
+ const {
+ threshold = 0.1,
+ rootMargin = "50px",
+ triggerOnce = true,
+ } = options;
+
+ useEffect(() => {
+ const currentElement = ref.current;
+
+ if (!currentElement) return;
+
+ // If already visible and triggerOnce is true, don't set up observer
+ if (hasTriggered && triggerOnce) {
+ return;
+ }
+
+ const observer = new IntersectionObserver(
+ ([entry]) => {
+ if (entry.isIntersecting) {
+ setIsVisible(true);
+ setHasTriggered(true);
+
+ if (triggerOnce) {
+ observer.unobserve(currentElement);
+ }
+ } else if (!triggerOnce) {
+ setIsVisible(false);
+ }
+ },
+ {
+ threshold,
+ rootMargin,
+ }
+ );
+
+ observer.observe(currentElement);
+
+ return () => {
+ observer.unobserve(currentElement);
+ };
+ }, [threshold, rootMargin, triggerOnce, hasTriggered]);
+
+ return [ref as any, isVisible];
+};
+
+interface UseLazyLoadProps {
+ threshold?: number;
+ rootMargin?: string;
+}
+
+export const useLazyLoad = (
+ options: UseLazyLoadProps = {}
+): [React.RefObject, boolean, boolean] => {
+ const ref = useRef(null);
+ const [isVisible, setIsVisible] = useState(false);
+ const [isLoading, setIsLoading] = useState(true);
+
+ const { threshold = 0.1, rootMargin = "50px" } = options;
+
+ useEffect(() => {
+ const currentElement = ref.current;
+
+ if (!currentElement) return;
+
+ const observer = new IntersectionObserver(
+ ([entry]) => {
+ if (entry.isIntersecting) {
+ setIsVisible(true);
+ // Simulate loading time
+ setTimeout(() => {
+ setIsLoading(false);
+ }, 300);
+
+ observer.unobserve(currentElement);
+ }
+ },
+ {
+ threshold,
+ rootMargin,
+ }
+ );
+
+ observer.observe(currentElement);
+
+ return () => {
+ observer.unobserve(currentElement);
+ };
+ }, [threshold, rootMargin]);
+
+ return [ref as any, isVisible, isLoading];
+};
diff --git a/frontend/src/components/sections/AboutSection.tsx b/frontend/src/components/sections/AboutSection.tsx
new file mode 100644
index 0000000..4da5c0d
--- /dev/null
+++ b/frontend/src/components/sections/AboutSection.tsx
@@ -0,0 +1,47 @@
+"use client";
+
+import Image from "next/image";
+
+export default function AboutSection() {
+ return (
+
+
+
+
+
+ Chi Siamo
+
+
+ CiMa Progetti unisce architettura e software engineering. Costruiamo
+ sistemi digitali solidi e scalabili per aziende che non accettano
+ compromessi.
+
+
+
+
AI Expert
+
+ Nicola Leone Ciardi
+
+
+
+
Jr Engineer
+
+ Valentina Madaudo
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/components/sections/ServicesSection.tsx b/frontend/src/components/sections/ServicesSection.tsx
new file mode 100644
index 0000000..1966660
--- /dev/null
+++ b/frontend/src/components/sections/ServicesSection.tsx
@@ -0,0 +1,99 @@
+"use client";
+
+export default function ServicesSection() {
+ return (
+
+
+
+
+
+ Cosa Facciamo
+
+
+
+ Soluzioni su misura per il vostro metodo di lavoro. Automazione,
+ gestione dati e competenze umane in un unico flusso.
+
+
+
+
+
+ {/* Portali */}
+
+
+ hub
+
+
+ Portali & Infrastrutture Digitali
+
+
+ Siti, portali e web app costruiti per funzionare e crescere con
+ voi.
+
+
+
+ {/* Database */}
+
+
+ schema
+
+
+ Database & Sistemi Gestionali
+
+
+ I vostri dati organizzati, accessibili e pronti per le decisioni
+ che contano.
+
+
+
+ {/* E-commerce */}
+
+
+ shopping_bag
+
+
+ E-commerce & Piattaforme
+
+
+ Vendita online integrata con la vostra logistica, pronta a
+ scalare.
+
+
+
+ {/* Automazioni & IA */}
+
+
+
+ Automazioni & IA
+
+
+ Meno lavoro ripetitivo, più tempo per quello che conta.
+
+ IA anche in locale, i vostri dati restano vostri.
+
+
+
+ memory
+
+
+
+ {/* Cybersicurezza */}
+
+
+
+ Cybersicurezza
+
+
+ Protezione proattiva e monitoraggio continuo dei vostri asset
+ digitali.
+
+
+
+ verified_user
+
+
+
+
+
+ );
+}