From 9aeaeafa3f03010eb13067fd4d326fe290cd41be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mauricio=20L=C3=B3pez=20Coria?= Date: Wed, 1 Jul 2026 23:16:36 -0300 Subject: [PATCH] feat: Awwwards transformation Phases 1-6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 1 — Design System: - Glassmorphism tokens (--glass-bg, --glass-border, --blur-glass) - Gradient tokens (--hds-gradient-hero, --hds-gradient-section) - Motion tokens (--ease-spring, --ease-out-expo) - .glass-card component class with hover uplift + mouse-tracking glow - .noise-overlay: SVG feTurbulence texture at 0.025 opacity - Buttons with spring easing, prefers-reduced-motion support Phase 2 — Preloader + Hero: - Preloader.astro: vanilla JS logo fade-in + loading bar + slide-up - Uses sessionStorage to skip on repeat visits - Hero.astro: full-bleed 100dvh, GSAP timeline, glass ring decoration - Parallax floating SVG shapes (sine yoyo animation) - i18n: hero.scrollDown key Phase 3 — 'Por qué elegirnos' Bento Grid: - DifferenceCards.astro: asymmetric 3-column bento grid - Glass cards with mouse-tracking glow (--mouse-x/--mouse-y) - GSAP ScrollTrigger stagger reveal (opacity 0→1, y: 40→0) Phase 4 — Pricing + Process: - planes.astro: 5 visible + 4 in details accordion - Empresarial as hero card, price annual only (no toggle) - ProcessSteps.astro: timeline + ScrollTrigger progress bar Phase 5 — Global Polish: - LenisScroll.astro: smooth scroll (duration 1.2, cubic easing) - GSAP ticker sync, noise overlay in BaseLayout Phase 6 — Deploy: - deploy.sh: auto-detects repo path, auto-builds if stale - Relative paths instead of hardcoded /root/opencode/development --- package-lock.json | 15 ++ package.json | 2 + scripts/deploy.sh | 22 ++- src/components/DifferenceCards.astro | 126 ++++++++++++++-- src/components/FaqSection.astro | 2 +- src/components/Hero.astro | 217 +++++++++++++++++++++++---- src/components/LenisScroll.astro | 37 +++++ src/components/Preloader.astro | 80 ++++++++++ src/components/ProcessSteps.astro | 143 +++++++++++++++--- src/components/ServiceCard.astro | 2 +- src/i18n/ui.ts | 2 + src/layouts/BaseLayout.astro | 5 + src/pages/planes.astro | 206 +++++++++++++++++++------ src/styles/global.css | 160 ++++++++++++++++++-- 14 files changed, 896 insertions(+), 123 deletions(-) create mode 100644 src/components/LenisScroll.astro create mode 100644 src/components/Preloader.astro diff --git a/package-lock.json b/package-lock.json index d04b99c..a70a833 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,8 +14,10 @@ "@fontsource/mulish": "^5.1.0", "@fontsource/quicksand": "^5.2.10", "@keystatic/core": "^0.5.0", + "@studio-freight/lenis": "^1.0.42", "@tailwindcss/vite": "^4.0.0", "astro": "^5.0.0", + "gsap": "^3.15.0", "sharp": "^0.33.5", "tailwindcss": "^4.0.0" }, @@ -4004,6 +4006,13 @@ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, + "node_modules/@studio-freight/lenis": { + "version": "1.0.42", + "resolved": "https://registry.npmjs.org/@studio-freight/lenis/-/lenis-1.0.42.tgz", + "integrity": "sha512-HJAGf2DeM+BTvKzHv752z6Z7zy6bA643nZM7W88Ft9tnw2GsJSp6iJ+3cekjyMIWH+cloL2U9X82dKXgdU8kPg==", + "deprecated": "The '@studio-freight/lenis' package has been renamed to 'lenis'. Please update your dependencies: npm install lenis and visit the documentation: https://www.npmjs.com/package/lenis", + "license": "MIT" + }, "node_modules/@swc/helpers": { "version": "0.5.23", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", @@ -6664,6 +6673,12 @@ "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, + "node_modules/gsap": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.15.0.tgz", + "integrity": "sha512-dMW4CWBTUK1AEEDeZc1g4xpPGIrSf9fJF960qbTZmN/QwZIWY5wgliS6JWl9/25fpTGJrMRtSjGtOmPnfjZB+A==", + "license": "Standard 'no charge' license: https://gsap.com/standard-license." + }, "node_modules/h3": { "version": "1.15.11", "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz", diff --git a/package.json b/package.json index 818dfd9..90e85d3 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,10 @@ "@fontsource/mulish": "^5.1.0", "@fontsource/quicksand": "^5.2.10", "@keystatic/core": "^0.5.0", + "@studio-freight/lenis": "^1.0.42", "@tailwindcss/vite": "^4.0.0", "astro": "^5.0.0", + "gsap": "^3.15.0", "sharp": "^0.33.5", "tailwindcss": "^4.0.0" }, diff --git a/scripts/deploy.sh b/scripts/deploy.sh index f532b59..d3e747c 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -1,24 +1,32 @@ #!/bin/bash set -e -DIST="/root/opencode/development/hostingdelsur.net/dist" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO="$(dirname "$SCRIPT_DIR")" +DIST="$REPO/dist" REMOTE="server1" REMOTE_PATH="/home/hostingd/public_html" -LOCAL_USER="root" echo "=== Deploy hostingdelsur.net (rsync) ===" -echo "Local: $DIST" +echo "Repo: $REPO" +echo "Dist: $DIST" echo "Remote: $REMOTE:$REMOTE_PATH" echo "" +# Build if dist doesn't exist or is stale +if [ ! -d "$DIST" ] || [ "$REPO/package.json" -nt "$DIST" ]; then + echo "→ Building..." + npm run build --prefix "$REPO" +fi + # Copy PHP endpoints into dist (they don't go through Astro) mkdir -p "$DIST/api" -cp /root/opencode/development/hostingdelsur.net/src/forms/contact.php "$DIST/api/contact.php" -cp /root/opencode/development/hostingdelsur.net/src/forms/deploy-webhook.php "$DIST/api/deploy-webhook.php" -cp /root/opencode/development/hostingdelsur.net/src/forms/api-htaccess "$DIST/api/.htaccess" +cp "$REPO/src/forms/contact.php" "$DIST/api/contact.php" +cp "$REPO/src/forms/deploy-webhook.php" "$DIST/api/deploy-webhook.php" +cp "$REPO/src/forms/api-htaccess" "$DIST/api/.htaccess" # Copy root .htaccess (HTTPS forzado, security headers) -cp /root/opencode/development/hostingdelsur.net/scripts/htaccess.conf "$DIST/.htaccess" +cp "$REPO/scripts/htaccess.conf" "$DIST/.htaccess" # cPanel recognizes 404.shtml specifically (Server-Side Includes) # Astro generates 404.html — duplicate as .shtml for cPanel diff --git a/src/components/DifferenceCards.astro b/src/components/DifferenceCards.astro index 21ae340..7e12c8b 100644 --- a/src/components/DifferenceCards.astro +++ b/src/components/DifferenceCards.astro @@ -1,4 +1,6 @@ --- +// "Por qué elegirnos" — Bento grid with glass cards + magnetic hover glow +// Phase 3 — Organic Fluidity Premium import SectionEyebrow from './SectionEyebrow.astro'; import type { TranslationKey } from '@/i18n/ui'; import MateIcon from './icons/MateIcon.astro'; @@ -10,15 +12,23 @@ interface Props { } const { t } = Astro.props; -const items = [ - { Icon: MateIcon, titleKey: 'diff.support.title' as TranslationKey, bodyKey: 'diff.support.body' as TranslationKey }, +interface DiffItem { + Icon?: typeof MateIcon; + titleKey: TranslationKey; + bodyKey: TranslationKey; + hero?: boolean; + area?: string; +} + +const items: DiffItem[] = [ + { Icon: MateIcon, titleKey: 'diff.support.title' as TranslationKey, bodyKey: 'diff.support.body' as TranslationKey, hero: true }, { Icon: SovereigntyIcon, titleKey: 'diff.sovereignty.title' as TranslationKey, bodyKey: 'diff.sovereignty.body' as TranslationKey }, { Icon: GlobeIcon, titleKey: 'diff.infra.title' as TranslationKey, bodyKey: 'diff.infra.body' as TranslationKey }, ]; --- -
+
-
+

{t('diff.title')} @@ -28,20 +38,116 @@ const items = [

-
- {items.map((item) => ( -
+ +
+ {items.map((item, i) => ( +
- + {item.Icon && }
-

+

{t(item.titleKey)}

-

+

{t(item.bodyKey)}

+ + {item.hero && ( +
+
+
M
+
+2
+
+ + {t('diff.eyebrow') === 'La diferencia' ? 'Equipo de 3 ingenieros SRE' : 'Team of 3 SRE engineers'} + +
+ )}
))}
+ + + + diff --git a/src/components/FaqSection.astro b/src/components/FaqSection.astro index 0675e3f..5b8cf16 100644 --- a/src/components/FaqSection.astro +++ b/src/components/FaqSection.astro @@ -50,7 +50,7 @@ const faqs = lang === 'en' ? [
-
+
diff --git a/src/components/Hero.astro b/src/components/Hero.astro index 78ec89a..9a588e6 100644 --- a/src/components/Hero.astro +++ b/src/components/Hero.astro @@ -8,50 +8,90 @@ interface Props { const { t, whatsappUrl } = Astro.props; --- -
- - +
+ + -
+ + + + diff --git a/src/components/LenisScroll.astro b/src/components/LenisScroll.astro new file mode 100644 index 0000000..9b04284 --- /dev/null +++ b/src/components/LenisScroll.astro @@ -0,0 +1,37 @@ +--- +// Lenis smooth scroll — Phase 5 +// Synced with GSAP ticker for scroll-driven animations +--- + diff --git a/src/components/Preloader.astro b/src/components/Preloader.astro new file mode 100644 index 0000000..adb3d1e --- /dev/null +++ b/src/components/Preloader.astro @@ -0,0 +1,80 @@ +--- +// Preloader: logo scale-in + loading bar + split-door reveal +// Phase 2 — Organic Fluidity Premium +--- +
+
+ +
+
+
+
+
+ + + + diff --git a/src/components/ProcessSteps.astro b/src/components/ProcessSteps.astro index f1de5b5..6e6702f 100644 --- a/src/components/ProcessSteps.astro +++ b/src/components/ProcessSteps.astro @@ -1,6 +1,12 @@ --- +// "Cómo trabajamos" — Timeline with GSAP ScrollTrigger progress bar +// Phase 4 — Organic Fluidity Premium import SectionEyebrow from './SectionEyebrow.astro'; import type { TranslationKey } from '@/i18n/ui'; +import gsap from 'gsap'; +import { ScrollTrigger } from 'gsap/ScrollTrigger'; + +gsap.registerPlugin(ScrollTrigger); interface Props { t: (key: TranslationKey) => string; @@ -14,32 +20,133 @@ const steps = [ { num: '04', titleKey: 'process.step4.title' as TranslationKey, bodyKey: 'process.step4.body' as TranslationKey }, ]; --- -
+
+ +
-
+

{t('process.title')}

-
    - + +
    + + - {steps.map((step) => ( -
  1. -
  2. - ))} -
+ ))} +
+
+ + + + diff --git a/src/components/ServiceCard.astro b/src/components/ServiceCard.astro index 771a92a..d174593 100644 --- a/src/components/ServiceCard.astro +++ b/src/components/ServiceCard.astro @@ -13,7 +13,7 @@ const { href, title, description, Icon, borderColor = 'var(--color-hds-naranja)' ---
diff --git a/src/i18n/ui.ts b/src/i18n/ui.ts index d1afbf2..cd9eec2 100644 --- a/src/i18n/ui.ts +++ b/src/i18n/ui.ts @@ -15,6 +15,7 @@ export const ui = { 'hero.badgeUptime': 'Uptime 99.9%', 'hero.badgeSupport': 'Soporte humano', 'hero.badgeLocation': 'Maldonado, Uruguay', + 'hero.scrollDown': 'Deslizá', 'stats.label1': 'Años de experiencia', 'stats.sub1': 'Desde el 2000', 'stats.label2': 'Proyectos hospedados', @@ -80,6 +81,7 @@ export const ui = { 'hero.badgeUptime': '99.9% uptime', 'hero.badgeSupport': 'Human support', 'hero.badgeLocation': 'Maldonado, Uruguay', + 'hero.scrollDown': 'Scroll', 'stats.label1': 'Years of experience', 'stats.sub1': 'Since 2000', 'stats.label2': 'Projects hosted', diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index cf893d2..43d4131 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -19,9 +19,11 @@ const canonicalUrl = canonical ? `${siteUrl}${canonical}` : `${siteUrl}${Astro.u import '@/styles/global.css'; import Navbar from '@/components/Navbar.astro'; import Footer from '@/components/Footer.astro'; +import Preloader from '@/components/Preloader.astro'; import WhatsappFab from '@/components/WhatsappFab.astro'; import BackToTop from '@/components/BackToTop.astro'; import ScrollReveal from '@/components/ScrollReveal.astro'; +import LenisScroll from '@/components/LenisScroll.astro'; const orgJsonLd = { '@context': 'https://schema.org', @@ -116,11 +118,14 @@ const localBusinessJsonLd = { + +