8 Commits

Author SHA1 Message Date
08c50879b7 Merge version_3 into main
Merge version_3 into main
2026-03-03 06:04:22 +00:00
4a8b351772 Update theme fonts 2026-03-03 06:04:18 +00:00
875fdd4c97 Update theme fonts 2026-03-03 06:04:17 +00:00
9dc9a1ff72 Merge version_3 into main
Merge version_3 into main
2026-03-03 06:02:51 +00:00
10e94075af Update src/app/page.tsx 2026-03-03 06:02:47 +00:00
270f4205a8 Merge version_2 into main
Merge version_2 into main
2026-03-03 06:00:48 +00:00
127fec21f3 Update src/app/page.tsx 2026-03-03 06:00:43 +00:00
f36df32471 Update src/app/layout.tsx 2026-03-03 06:00:43 +00:00
3 changed files with 57 additions and 89 deletions

View File

@@ -5,34 +5,25 @@ import { Open_Sans } from "next/font/google";
import "./globals.css"; import "./globals.css";
import { ServiceWrapper } from "@/components/ServiceWrapper"; import { ServiceWrapper } from "@/components/ServiceWrapper";
import Tag from "@/tag/Tag"; import Tag from "@/tag/Tag";
import { Montserrat } from "next/font/google";
const halant = Halant({
variable: "--font-halant", subsets: ["latin"],
weight: ["300", "400", "500", "600", "700"],
});
const inter = Inter({
variable: "--font-inter", subsets: ["latin"],
});
const openSans = Open_Sans({
variable: "--font-open-sans", subsets: ["latin"],
});
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Proof Digital - Award-Winning Digital Agency", description: "Transform your digital vision into reality with Proof Digital. We deliver strategic design, development, and marketing solutions for ambitious brands.", keywords: "digital agency, web design, development, digital marketing, UX design, brand strategy", metadataBase: new URL("https://proofdigital.com"), title: "Draco Digital - Award-Winning Digital Agency", description: "Transform your digital vision into reality with Draco Digital. We deliver strategic design, development, and marketing solutions for ambitious brands.", keywords: "digital agency, web design, development, digital marketing, UX design, brand strategy", metadataBase: new URL("https://dracodigital.com"),
alternates: { alternates: {
canonical: "https://proofdigital.com" canonical: "https://dracodigital.com"
}, },
openGraph: { openGraph: {
title: "Proof Digital - Award-Winning Digital Agency", description: "Strategic design & development for digital transformation", url: "https://proofdigital.com", siteName: "Proof Digital", type: "website", images: [ title: "Draco Digital - Award-Winning Digital Agency", description: "Strategic design & development for digital transformation", url: "https://dracodigital.com", siteName: "Draco Digital", type: "website", images: [
{ {
url: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AQFKBKtzUE9UtHpu5cFGLuPTXL/a-modern-sleek-digital-agency-dashboard--1772516969990-f3574ef1.png", alt: "Proof Digital Hero Dashboard" url: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AQFKBKtzUE9UtHpu5cFGLuPTXL/a-modern-sleek-digital-agency-dashboard--1772516969990-f3574ef1.png", alt: "Draco Digital Hero Dashboard"
} }
] ]
}, },
twitter: { twitter: {
card: "summary_large_image", title: "Proof Digital - Award-Winning Digital Agency", description: "Strategic design & development for digital transformation", images: ["https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AQFKBKtzUE9UtHpu5cFGLuPTXL/a-modern-sleek-digital-agency-dashboard--1772516969990-f3574ef1.png"] card: "summary_large_image", title: "Draco Digital - Award-Winning Digital Agency", description: "Strategic design & development for digital transformation", images: ["https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AQFKBKtzUE9UtHpu5cFGLuPTXL/a-modern-sleek-digital-agency-dashboard--1772516969990-f3574ef1.png"]
}, },
robots: { robots: {
index: true, index: true,
@@ -40,6 +31,15 @@ export const metadata: Metadata = {
} }
}; };
const montserrat = Montserrat({
variable: "--font-montserrat",
subsets: ["latin"],
});
const inter = Inter({
variable: "--font-inter",
subsets: ["latin"],
});
export default function RootLayout({ export default function RootLayout({
children, children,
}: Readonly<{ }: Readonly<{
@@ -48,9 +48,7 @@ export default function RootLayout({
return ( return (
<html lang="en" suppressHydrationWarning> <html lang="en" suppressHydrationWarning>
<ServiceWrapper> <ServiceWrapper>
<body <body className={`${montserrat.variable} ${inter.variable} antialiased`}>
className={`${halant.variable} ${inter.variable} ${openSans.variable} antialiased`}
>
<Tag /> <Tag />
{children} {children}
@@ -295,8 +293,6 @@ export default function RootLayout({
const getElementInfo = (element, assignId = false) => { const getElementInfo = (element, assignId = false) => {
const rect = element.getBoundingClientRect(); const rect = element.getBoundingClientRect();
const tagName = element.tagName.toLowerCase(); const tagName = element.tagName.toLowerCase();
const selector = getUniqueSelector(element, assignId);
const sectionId = getSectionId(element);
let className = undefined; let className = undefined;
try { try {
@@ -325,8 +321,7 @@ export default function RootLayout({
}; };
if (tagName === 'img') { if (tagName === 'img') {
const originalSrc = extractOriginalUrl(element.src); info.imageData = {
info.imageData = {
src: originalSrc, src: originalSrc,
alt: element.alt || undefined, alt: element.alt || undefined,
naturalWidth: element.naturalWidth, naturalWidth: element.naturalWidth,
@@ -337,8 +332,7 @@ export default function RootLayout({
if (tagName === 'video') { if (tagName === 'video') {
const rawSrc = element.src || element.currentSrc || (element.querySelector('source') && element.querySelector('source').src) || ''; const rawSrc = element.src || element.currentSrc || (element.querySelector('source') && element.querySelector('source').src) || '';
const resolvedSrc = extractOriginalUrl(rawSrc); info.imageData = {
info.imageData = {
src: resolvedSrc, src: resolvedSrc,
alt: element.getAttribute('aria-label') || undefined, alt: element.getAttribute('aria-label') || undefined,
isBackground: false, isBackground: false,
@@ -351,8 +345,7 @@ export default function RootLayout({
if (backgroundImage && backgroundImage !== 'none') { if (backgroundImage && backgroundImage !== 'none') {
const urlMatch = backgroundImage.match(/url(['"]?([^'")]+)['"]?)/); const urlMatch = backgroundImage.match(/url(['"]?([^'")]+)['"]?)/);
if (urlMatch) { if (urlMatch) {
const originalBgSrc = extractOriginalUrl(urlMatch[1]); if (tagName !== 'img') {
if (tagName !== 'img') {
info.imageData = { info.imageData = {
src: originalBgSrc, src: originalBgSrc,
isBackground: true isBackground: true
@@ -364,8 +357,7 @@ export default function RootLayout({
} }
} }
const elementType = getElementType(element); info.elementType = elementType;
info.elementType = elementType;
if (elementType === 'Button') { if (elementType === 'Button') {
const buttonText = element.textContent?.trim() || element.value || element.getAttribute('aria-label') || ''; const buttonText = element.textContent?.trim() || element.value || element.getAttribute('aria-label') || '';
@@ -458,13 +450,11 @@ export default function RootLayout({
}; };
const isTextElement = (element) => { const isTextElement = (element) => {
const elementType = getElementType(element); return elementType === 'Text';
return elementType === 'Text';
}; };
const isButtonElement = (element) => { const isButtonElement = (element) => {
const elementType = getElementType(element); return elementType === 'Button';
return elementType === 'Button';
}; };
const updateButtonText = (element, newText) => { const updateButtonText = (element, newText) => {
@@ -539,8 +529,7 @@ export default function RootLayout({
}; };
const handleInput = () => { const handleInput = () => {
const elementInfo = getElementInfo(element); let currentText = element.textContent;
let currentText = element.textContent;
// Ensure there's always at least a space to keep the element editable // Ensure there's always at least a space to keep the element editable
if (currentText === '' || currentText === null || currentText.length === 0) { if (currentText === '' || currentText === null || currentText.length === 0) {
@@ -653,8 +642,7 @@ export default function RootLayout({
}, '*'); }, '*');
if (save && originalContent !== element.textContent) { if (save && originalContent !== element.textContent) {
const elementInfo = getElementInfo(element); let finalText = element.textContent;
let finalText = element.textContent;
// Trim the final text and convert space-only to empty string for saving // Trim the final text and convert space-only to empty string for saving
if (finalText === ' ' || finalText.trim() === '') { if (finalText === ' ' || finalText.trim() === '') {
@@ -783,7 +771,7 @@ export default function RootLayout({
lastMouseX = e.clientX; lastMouseX = e.clientX;
lastMouseY = e.clientY; lastMouseY = e.clientY;
const target = getMostSpecificElement(e.clientX, e.clientY) || e.target; || e.target;
if (!isValidElement(target) || target === hoveredElement || target === selectedElement) { if (!isValidElement(target) || target === hoveredElement || target === selectedElement) {
return; return;
@@ -815,8 +803,7 @@ export default function RootLayout({
hoverOverlay = createHoverOverlay(target); hoverOverlay = createHoverOverlay(target);
} }
const elementType = getElementType(target); showElementTypeLabel(target, elementType);
showElementTypeLabel(target, elementType);
window.parent.postMessage({ window.parent.postMessage({
type: 'webild-element-hover', type: 'webild-element-hover',
@@ -858,7 +845,7 @@ export default function RootLayout({
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
const target = getMostSpecificElement(e.clientX, e.clientY) || e.target; || e.target;
if (!isValidElement(target)) return; if (!isValidElement(target)) return;
if (selectedElement && selectedElement !== target) { if (selectedElement && selectedElement !== target) {
@@ -903,8 +890,7 @@ export default function RootLayout({
hoveredElement = null; hoveredElement = null;
} }
const elementInfo = getElementInfo(target, true); selectedElement.dataset.webildSelector = elementInfo.selector;
selectedElement.dataset.webildSelector = elementInfo.selector;
showElementTypeLabel(target, elementInfo.elementType); showElementTypeLabel(target, elementInfo.elementType);
window.parent.postMessage({ window.parent.postMessage({
@@ -987,8 +973,7 @@ export default function RootLayout({
isScrolling = false; isScrolling = false;
if (lastMouseX > 0 && lastMouseY > 0) { if (lastMouseX > 0 && lastMouseY > 0) {
const target = getMostSpecificElement(lastMouseX, lastMouseY); if (target && isValidElement(target) && target !== selectedElement) {
if (target && isValidElement(target) && target !== selectedElement) {
hoveredElement = target; hoveredElement = target;
const computedStyle = window.getComputedStyle(target); const computedStyle = window.getComputedStyle(target);
@@ -1002,8 +987,7 @@ export default function RootLayout({
hoveredElement.classList.add(hoverClass); hoveredElement.classList.add(hoverClass);
hoverOverlay = createHoverOverlay(target); hoverOverlay = createHoverOverlay(target);
const elementType = getElementType(target); showElementTypeLabel(target, elementType);
showElementTypeLabel(target, elementType);
window.parent.postMessage({ window.parent.postMessage({
type: 'webild-element-hover', type: 'webild-element-hover',
@@ -1026,8 +1010,7 @@ export default function RootLayout({
const saveChangeToStorage = (change) => { const saveChangeToStorage = (change) => {
try { try {
const storageKey = getStorageKey(); const existingChanges = JSON.parse(localStorage.getItem(storageKey) || '[]');
const existingChanges = JSON.parse(localStorage.getItem(storageKey) || '[]');
const filteredChanges = existingChanges.filter(c => { const filteredChanges = existingChanges.filter(c => {
return !(c.oldValue === change.oldValue && c.sectionId === change.sectionId); return !(c.oldValue === change.oldValue && c.sectionId === change.sectionId);
@@ -1047,8 +1030,7 @@ export default function RootLayout({
const clearLocalChanges = () => { const clearLocalChanges = () => {
try { try {
const storageKey = getStorageKey(); localStorage.removeItem(storageKey);
localStorage.removeItem(storageKey);
window.parent.postMessage({ window.parent.postMessage({
type: 'webild-local-changes-cleared', type: 'webild-local-changes-cleared',
data: {} data: {}
@@ -1097,8 +1079,7 @@ export default function RootLayout({
if (e.data.type === 'webild-cancel-changes') { if (e.data.type === 'webild-cancel-changes') {
try { try {
const storageKey = getStorageKey(); const savedChanges = localStorage.getItem(storageKey);
const savedChanges = localStorage.getItem(storageKey);
if (savedChanges) { if (savedChanges) {
const changes = JSON.parse(savedChanges); const changes = JSON.parse(savedChanges);
changes.forEach(change => { changes.forEach(change => {
@@ -1120,8 +1101,7 @@ export default function RootLayout({
if (isBackground) { if (isBackground) {
element.style.backgroundImage = change.oldValue ? 'url(' + change.oldValue + ')' : ''; element.style.backgroundImage = change.oldValue ? 'url(' + change.oldValue + ')' : '';
} else { } else {
const oldMediaType = getMediaTypeFromUrl(change.oldValue); if (revertTag === 'video' && oldMediaType === 'image') {
if (revertTag === 'video' && oldMediaType === 'image') {
swapMediaElement(element, 'img', change.oldValue); swapMediaElement(element, 'img', change.oldValue);
} else if (revertTag === 'img' && oldMediaType === 'video') { } else if (revertTag === 'img' && oldMediaType === 'video') {
swapMediaElement(element, 'video', change.oldValue); swapMediaElement(element, 'video', change.oldValue);
@@ -1169,8 +1149,7 @@ export default function RootLayout({
const el = textElements[i]; const el = textElements[i];
if (isTextElement(el) && el.textContent.trim() === (oldValue || '').trim()) { if (isTextElement(el) && el.textContent.trim() === (oldValue || '').trim()) {
element = el; element = el;
const newSelector = getUniqueSelector(element, true); if (newSelector) {
if (newSelector) {
element.dataset.webildSelector = newSelector; element.dataset.webildSelector = newSelector;
} }
break; break;
@@ -1261,10 +1240,8 @@ export default function RootLayout({
replaced = true; replaced = true;
} else if (element.tagName.toLowerCase() === 'img') { } else if (element.tagName.toLowerCase() === 'img') {
oldValue = element.src; oldValue = element.src;
const newMediaType = getMediaTypeFromUrl(newSrc); if (newMediaType === 'video' && allowMediaTypeSwap) {
if (newMediaType === 'video' && allowMediaTypeSwap) { if (selectedElement === element) selectedElement = swapped;
const swapped = swapMediaElement(element, 'video', newSrc);
if (selectedElement === element) selectedElement = swapped;
element = swapped; element = swapped;
} else { } else {
element.src = newSrc; element.src = newSrc;
@@ -1272,11 +1249,9 @@ export default function RootLayout({
replaced = true; replaced = true;
} else if (element.tagName.toLowerCase() === 'video') { } else if (element.tagName.toLowerCase() === 'video') {
oldValue = element.src || element.currentSrc || ''; oldValue = element.src || element.currentSrc || '';
const newMediaType = getMediaTypeFromUrl(newSrc); const sources = element.querySelectorAll('source');
const sources = element.querySelectorAll('source');
if (newMediaType === 'image' && allowMediaTypeSwap) { if (newMediaType === 'image' && allowMediaTypeSwap) {
const swapped = swapMediaElement(element, 'img', newSrc); if (selectedElement === element) selectedElement = swapped;
if (selectedElement === element) selectedElement = swapped;
element = swapped; element = swapped;
} else { } else {
if (sources.length > 0) { if (sources.length > 0) {
@@ -1298,7 +1273,6 @@ export default function RootLayout({
} }
if (replaced) { if (replaced) {
const elementInfo = getElementInfo(element);
let cleanOldValue = oldValue; let cleanOldValue = oldValue;
if (oldValue.includes('url(')) { if (oldValue.includes('url(')) {
@@ -1370,12 +1344,6 @@ export default function RootLayout({
} }
}, true); }, true);
const urlCheckInterval = setInterval(() => {
if (lastPathname !== window.location.pathname) {
lastPathname = window.location.pathname;
notifyPageChange();
}
}, 500);
notifyPageChange(); notifyPageChange();

View File

@@ -28,7 +28,7 @@ export default function LandingPage() {
> >
<div id="nav" data-section="nav"> <div id="nav" data-section="nav">
<NavbarStyleApple <NavbarStyleApple
brandName="Proof Digital" brandName="Draco Digital"
navItems={[ navItems={[
{ name: "Services", id: "services" }, { name: "Services", id: "services" },
{ name: "Our Work", id: "work" }, { name: "Our Work", id: "work" },
@@ -52,7 +52,7 @@ export default function LandingPage() {
buttonAnimation="slide-up" buttonAnimation="slide-up"
background={{ variant: "glowing-orb" }} background={{ variant: "glowing-orb" }}
imageSrc="https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AQFKBKtzUE9UtHpu5cFGLuPTXL/a-modern-sleek-digital-agency-dashboard--1772516969990-f3574ef1.png" imageSrc="https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AQFKBKtzUE9UtHpu5cFGLuPTXL/a-modern-sleek-digital-agency-dashboard--1772516969990-f3574ef1.png"
imageAlt="Proof Digital dashboard interface" imageAlt="Draco Digital dashboard interface"
imagePosition="right" imagePosition="right"
mediaAnimation="slide-up" mediaAnimation="slide-up"
fixedMediaHeight={true} fixedMediaHeight={true}
@@ -61,9 +61,9 @@ export default function LandingPage() {
<div id="about" data-section="about"> <div id="about" data-section="about">
<TextSplitAbout <TextSplitAbout
title="About Proof Digital" title="About Draco Digital"
description={[ description={[
"At Proof Digital, we believe exceptional design and strategic thinking are the foundation of digital success. Our multidisciplinary team combines creativity, technology, and business acumen to deliver transformative solutions.", "With over a decade of experience, we've helped hundreds of brands across industries achieve their goals through intelligent digital strategy, beautiful design, and robust development. We're committed to understanding your unique challenges and crafting solutions that truly work.", "Our approach is collaborative, transparent, and results-driven. We don't just build websites—we build partnerships that drive measurable business impact." "At Draco Digital, we believe exceptional design and strategic thinking are the foundation of digital success. Our multidisciplinary team combines creativity, technology, and business acumen to deliver transformative solutions.", "With over a decade of experience, we've helped hundreds of brands across industries achieve their goals through intelligent digital strategy, beautiful design, and robust development. We're committed to understanding your unique challenges and crafting solutions that truly work.", "Our approach is collaborative, transparent, and results-driven. We don't just build websites—we build partnerships that drive measurable business impact."
]} ]}
buttons={[{ text: "Learn More", href: "services" }]} buttons={[{ text: "Learn More", href: "services" }]}
showBorder={false} showBorder={false}
@@ -185,7 +185,7 @@ export default function LandingPage() {
} }
]} ]}
imageSrc="https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AQFKBKtzUE9UtHpu5cFGLuPTXL/professional-customer-support-team-worki-1772516970613-7862134b.png" imageSrc="https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AQFKBKtzUE9UtHpu5cFGLuPTXL/professional-customer-support-team-worki-1772516970613-7862134b.png"
imageAlt="Proof Digital support team" imageAlt="Draco Digital support team"
mediaAnimation="slide-up" mediaAnimation="slide-up"
mediaPosition="left" mediaPosition="left"
faqsAnimation="slide-up" faqsAnimation="slide-up"
@@ -198,8 +198,8 @@ export default function LandingPage() {
<div id="contact" data-section="contact"> <div id="contact" data-section="contact">
<ContactFaq <ContactFaq
ctaTitle="Ready to Transform Your Digital Presence?" ctaTitle="Ready to Transform Your Digital Presence?"
ctaDescription="Let's discuss how Proof Digital can help you achieve your business goals through strategic digital solutions." ctaDescription="Let's discuss how Draco Digital can help you achieve your business goals through strategic digital solutions."
ctaButton={{ text: "Schedule a Consultation", href: "https://calendly.com" }} ctaButton={{ text: "Book Your Free Consultation Call", href: "https://calendly.com" }}
ctaIcon={Phone} ctaIcon={Phone}
faqs={[ faqs={[
{ {
@@ -219,8 +219,8 @@ export default function LandingPage() {
<div id="footer" data-section="footer"> <div id="footer" data-section="footer">
<FooterBase <FooterBase
logoText="Proof Digital" logoText="Draco Digital"
copyrightText="© 2025 Proof Digital. All rights reserved." copyrightText="© 2025 Draco Digital. All rights reserved."
columns={[ columns={[
{ {
title: "Services", items: [ title: "Services", items: [
@@ -235,15 +235,15 @@ export default function LandingPage() {
{ label: "About Us", href: "#about" }, { label: "About Us", href: "#about" },
{ label: "Our Work", href: "#work" }, { label: "Our Work", href: "#work" },
{ label: "Testimonials", href: "#testimonials" }, { label: "Testimonials", href: "#testimonials" },
{ label: "Blog", href: "https://blog.proofdigital.com" } { label: "Blog", href: "https://blog.dracodigital.com" }
] ]
}, },
{ {
title: "Connect", items: [ title: "Connect", items: [
{ label: "Contact Us", href: "#contact" }, { label: "Contact Us", href: "#contact" },
{ label: "LinkedIn", href: "https://linkedin.com/company/proof-digital" }, { label: "LinkedIn", href: "https://linkedin.com/company/draco-digital" },
{ label: "Twitter", href: "https://twitter.com/proofdigital" }, { label: "Twitter", href: "https://twitter.com/dracodigital" },
{ label: "Instagram", href: "https://instagram.com/proofdigital" } { label: "Instagram", href: "https://instagram.com/dracodigital" }
] ]
} }
]} ]}

View File

@@ -11,7 +11,7 @@ html {
body { body {
background-color: var(--background); background-color: var(--background);
color: var(--foreground); color: var(--foreground);
font-family: var(--font-open-sans), sans-serif; font-family: var(--font-inter), sans-serif;
position: relative; position: relative;
min-height: 100vh; min-height: 100vh;
overscroll-behavior: none; overscroll-behavior: none;
@@ -24,5 +24,5 @@ h3,
h4, h4,
h5, h5,
h6 { h6 {
font-family: var(--font-open-sans), sans-serif; font-family: var(--font-montserrat), sans-serif;
} }