diff --git a/README.md b/README.md index e9cf8b1..55b6179 100644 --- a/README.md +++ b/README.md @@ -61,4 +61,4 @@ Importa el repo en Vercel. `vercel.json` ya define el build (`npm run build`), l - **Press:** falta el link del artículo de Gulf Insider y confirmar su titular exacto (`FEATURE` en `src/pages/press.mjs`). - **Korrith:** falta el cargo de Dylan (el tercer campo, vacío, en `src/pages/portfolio.mjs`). - **Páginas fuera del alcance actual:** Playbook y Poetry no forman parte del sitio. Sus secciones se muestran sin botón; si se crean esas páginas, se añade el botón con su texto original del documento. -- **Formulario y agenda (GoHighLevel):** los IDs están en `SITE.ghl` (`src/layout.mjs`). En GoHighLevel, el formulario "Dylan – Lead Form" debe redirigir a `https://dylanmazzei.com/contact/book/` al enviarse. +- **Formulario y agenda (GoHighLevel):** los IDs están en `SITE.ghl` (`src/layout.mjs`). En GoHighLevel, el formulario "Dylan – Lead Form" debe redirigir a `https://dylanmazzei.com/contact/book/?submitted=1` al enviarse. Sin `?submitted=1`, `/contact/book/` muestra un aviso para llenar el formulario en vez de los calendarios (es solo un filtro en el navegador: los calendarios de GHL siguen siendo públicos, así que el cobro y la disponibilidad se controlan en GHL). La página no se indexa ni sale en el sitemap. diff --git a/build.mjs b/build.mjs index d4e90d9..7f9dcda 100644 --- a/build.mjs +++ b/build.mjs @@ -37,7 +37,7 @@ for (const name of pages) { await mkdir(dirname(file), { recursive: true }); await writeFile(file, fingerprint(html)); } - urls.push(def.path); + if (!def.noindex) urls.push(def.path); console.log('built', def.path); } for (const [l, set] of Object.entries(missing)) { diff --git a/src/i18n/ar.json b/src/i18n/ar.json index 91c313e..bc1dc14 100644 --- a/src/i18n/ar.json +++ b/src/i18n/ar.json @@ -1242,7 +1242,6 @@ "Give me enough context to understand what you’re working on, where things stand, and what you’d like to discuss.": "أعطني ما يكفي من السياق لأفهم ما تعمل عليه، وأين وصلت الأمور، وما الذي تود مناقشته.", "Dylan – Lead Form": "ديلان – نموذج التواصل", "Rather Put It on the Calendar?": "تفضّل حجز موعد مباشرة؟", - "If you already know a conversation makes sense, skip the back-and-forth and find a time that works.": "إن كنت تعرف بالفعل أن المحادثة منطقية، فتجاوز المراسلات المتبادلة واختر وقتًا يناسبك.", "NOT SURE WHERE TO START?": "لست متأكدًا من أين تبدأ؟", "See What I’m Working On First.": "اطّلع أولًا على ما أعمل عليه.", "If you want a little context before reaching out, explore the companies I operate today, see the businesses and exits that shaped my journey, or learn how I work with founders.": "إن أردت بعض السياق قبل التواصل، استكشف الشركات التي أديرها اليوم، أو اطّلع على الأعمال وصفقات التخارج التي شكّلت رحلتي، أو تعرّف على طريقة عملي مع المؤسسين.", @@ -1309,5 +1308,9 @@ "Building around new opportunities created by AI.": "البناء على الفرص الجديدة التي يخلقها الذكاء الاصطناعي.", "Creating technology designed for real classrooms.": "ابتكار تقنيات مصممة للفصول الدراسية الحقيقية.", "Solving security challenges for growing businesses.": "حل تحديات الأمن للشركات النامية.", - "Turning product ideas into businesses built around real customers.": "تحويل أفكار المنتجات إلى أعمال مبنية حول عملاء حقيقيين." + "Turning product ideas into businesses built around real customers.": "تحويل أفكار المنتجات إلى أعمال مبنية حول عملاء حقيقيين.", + "Send the form above and you’ll pick a time that works right after, no back-and-forth.": "أرسل النموذج أعلاه وستختار مباشرة بعده الوقت الذي يناسبك، دون مراسلات متبادلة.", + "Tell Me a Bit About You First.": "أخبرني قليلًا عن نفسك أولًا.", + "Send the short form on the contact page and you’ll pick a time for your call right after.": "أرسل النموذج القصير في صفحة التواصل وستختار موعد مكالمتك مباشرة بعده.", + "GO TO THE FORM": "انتقل إلى النموذج" } diff --git a/src/i18n/es.json b/src/i18n/es.json index 8f384b3..f4ae690 100644 --- a/src/i18n/es.json +++ b/src/i18n/es.json @@ -1242,7 +1242,6 @@ "Give me enough context to understand what you’re working on, where things stand, and what you’d like to discuss.": "Dame suficiente contexto para entender en qué estás trabajando, en qué punto están las cosas y de qué te gustaría hablar.", "Dylan – Lead Form": "Dylan – Formulario de contacto", "Rather Put It on the Calendar?": "¿Prefieres agendarlo directamente?", - "If you already know a conversation makes sense, skip the back-and-forth and find a time that works.": "Si ya sabes que una conversación tiene sentido, sáltate los mensajes de ida y vuelta y encuentra un horario que te funcione.", "NOT SURE WHERE TO START?": "¿NO SABES POR DÓNDE EMPEZAR?", "See What I’m Working On First.": "Mira primero en qué estoy trabajando.", "If you want a little context before reaching out, explore the companies I operate today, see the businesses and exits that shaped my journey, or learn how I work with founders.": "Si quieres un poco de contexto antes de escribir, explora las empresas que opero hoy, mira los negocios y ventas que marcaron mi camino o conoce cómo trabajo con fundadores.", @@ -1309,5 +1308,9 @@ "Building around new opportunities created by AI.": "Construyendo sobre las nuevas oportunidades que crea la IA.", "Creating technology designed for real classrooms.": "Creando tecnología pensada para aulas reales.", "Solving security challenges for growing businesses.": "Resolviendo retos de seguridad para negocios en crecimiento.", - "Turning product ideas into businesses built around real customers.": "Convirtiendo ideas de producto en negocios construidos alrededor de clientes reales." + "Turning product ideas into businesses built around real customers.": "Convirtiendo ideas de producto en negocios construidos alrededor de clientes reales.", + "Send the form above and you’ll pick a time that works right after, no back-and-forth.": "Envía el formulario de arriba y justo después eliges el horario que te funcione, sin mensajes de ida y vuelta.", + "Tell Me a Bit About You First.": "Primero cuéntame un poco sobre ti.", + "Send the short form on the contact page and you’ll pick a time for your call right after.": "Envía el formulario corto de la página de contacto y justo después eliges el horario de tu llamada.", + "GO TO THE FORM": "IR AL FORMULARIO" } diff --git a/src/layout.mjs b/src/layout.mjs index fb5d3b8..d5c4b05 100644 --- a/src/layout.mjs +++ b/src/layout.mjs @@ -7,8 +7,6 @@ export const SITE = { pressEmail: 'press@dylanmazzei.com', linkedin: 'https://www.linkedin.com/in/dylanmazzei/', instagram: 'https://www.instagram.com/thedylanmazzei', - // Replace with the real scheduling link (Calendly, Cal.com, etc.). - calendar: '/contact/book/', // GoHighLevel (LeadConnector) widgets. Contacts land in Dylan's GHL account. ghl: { form: 'xm10A7alZrxeKDtkMkD2', // "Dylan – Lead Form" @@ -281,5 +279,6 @@ ${scripts} export const GHL_SCRIPT = ''; export const ghlForm = (id, name) => ``; +// Calendars start without a src: book.js loads them once the visitor has sent the lead form. export const ghlCalendar = (id, title) => - ``; + ``; diff --git a/src/pages/book.mjs b/src/pages/book.mjs index e572a76..5f7afa1 100644 --- a/src/pages/book.mjs +++ b/src/pages/book.mjs @@ -1,6 +1,9 @@ import { icon, eyebrow, SITE, ghlCalendar, GHL_SCRIPT } from '../layout.mjs'; -// Step 2 of the GoHighLevel booking flow. The lead form redirects here after submit. +// Step 2 of the GoHighLevel booking flow. The lead form redirects here after submit, +// to /contact/book/?submitted=1. Visitors who did not come from the form see a prompt +// to fill it in instead of the calendars. This only hides the page: the calendars are +// still public GHL widgets, so the real limits (payment, availability) live in GHL. // Copy mirrors the "Book Your Call" step Gabriela built in GoHighLevel. const calls = [ { id: 'free', tag: 'FREE', h: 'Free 15-min intro call with Dylan’s team', p: 'Discover how we can support your business goals and see if we are the right match for your journey.', cta: 'Book free call', cal: SITE.ghl.freeCalendar, icon: 'users' }, @@ -9,6 +12,26 @@ const calls = [ export default { path: '/contact/book/', + noindex: true, + head: ``, title: 'Book Your Call | Dylan Mazzei', description: 'Book a free 15-minute intro call with Dylan Mazzei’s team or a 15-minute 1:1 session with Dylan.', scripts: GHL_SCRIPT + '\n', @@ -18,10 +41,17 @@ export default {
${eyebrow('BOOK YOUR CALL')} -

Thanks! Now choose your call.

-

Pick the option that fits you best.

+
+

Thanks! Now choose your call.

+

Pick the option that fits you best.

+
+
+

Tell Me a Bit About You First.

+

Send the short form on the contact page and you’ll pick a time for your call right after.

+ GO TO THE FORM${icon('arrow')} +
-
+
${calls .map( (c, i) => `
-
+
${calls .map( diff --git a/src/pages/contact.mjs b/src/pages/contact.mjs index 962cd68..dccb547 100644 --- a/src/pages/contact.mjs +++ b/src/pages/contact.mjs @@ -38,8 +38,8 @@ export default {
${ghlForm(SITE.ghl.form, 'Dylan – Lead Form')}
- -

Rather Put It on the Calendar?

If you already know a conversation makes sense, skip the back-and-forth and find a time that works.

+
+

Rather Put It on the Calendar?

Send the form above and you’ll pick a time that works right after, no back-and-forth.

${icon('calendar')}
diff --git a/static/assets/book.js b/static/assets/book.js index 36e0bdc..cd9345a 100644 --- a/static/assets/book.js +++ b/static/assets/book.js @@ -1,4 +1,6 @@ (function () { + if (document.documentElement.getAttribute('data-gate') !== 'open') return; + document.querySelectorAll('iframe[data-src]').forEach(function (f) { f.src = f.getAttribute('data-src'); }); var tabs = document.querySelectorAll('[data-call]'); var select = function (id, scroll) { tabs.forEach(function (t) { diff --git a/static/assets/site.js b/static/assets/site.js index a13738a..479248f 100644 --- a/static/assets/site.js +++ b/static/assets/site.js @@ -1,6 +1,8 @@ (function () { window.__site = true; var root = document.documentElement; + // The booking page uses this to keep visitors in the language they filled the form in. + if (!/\/contact\/book\//.test(location.pathname)) { try { sessionStorage.setItem('dm-lang', root.lang || 'en'); } catch (e) {} } // Translations for the current page's language, written into the page by the build. var T = function (s) { return (window.__i18n && window.__i18n[s]) || s; }; var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; diff --git a/static/assets/styles.css b/static/assets/styles.css index 061f23d..a363445 100644 --- a/static/assets/styles.css +++ b/static/assets/styles.css @@ -1055,6 +1055,7 @@ h1, h2, h3, h4 { font-weight: 600; } .cal-panel { max-width: 980px; margin: 0 auto; border-radius: 24px; } @media (max-width: 760px) { .calls { grid-template-columns: 1fr; } .call { padding: 24px; } } #schedule .wrap { position: relative; } +[data-gate="locked"] .gate-open, [data-gate="open"] .gate-locked, html:not([data-gate]) .gate-locked { display: none !important; } .cal-panel[data-off] { position: absolute; left: -10000px; top: 0; width: min(980px, 100%); visibility: hidden; pointer-events: none; } .ghl-wrap-form { min-height: 460px; } .ghl-wrap-cal { min-height: 720px; }