enhance ssr, add routes and enhance the header styles

This commit is contained in:
Mohammed Al-yaseen
2025-07-29 16:12:21 +03:00
parent b803532cde
commit 01ed3a2b7f
16 changed files with 1005 additions and 343 deletions

32
src/app/about/layout.tsx Normal file
View File

@@ -0,0 +1,32 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "About Us | Tech Master - Award-Winning IT Solutions Dubai",
description: "Learn about Tech Master, an award-winning Dubai-based technology agency specializing in digital transformation, web development, and innovative IT solutions since 2020.",
keywords: [
"about Tech Master",
"Dubai IT company",
"award-winning tech agency",
"digital transformation company",
"web development company Dubai",
"IT solutions provider",
"tech company Dubai",
"software development company"
],
openGraph: {
title: "About Us | Tech Master - Award-Winning IT Solutions Dubai",
description: "Learn about Tech Master, an award-winning Dubai-based technology agency specializing in digital transformation and innovative IT solutions.",
url: "https://tech-masters.guru/about",
},
alternates: {
canonical: "/about",
},
};
export default function AboutLayout({
children,
}: {
children: React.ReactNode;
}) {
return children;
}

253
src/app/about/page.tsx Normal file
View File

@@ -0,0 +1,253 @@
"use client";
import {
CheckCircleOutlined,
GlobalOutlined,
RocketOutlined,
StarOutlined,
TeamOutlined,
TrophyOutlined
} from "@ant-design/icons";
import { Avatar, Card, Col, Row, Typography } from "antd";
import { motion } from "framer-motion";
const { Title, Paragraph } = Typography;
export default function AboutPage() {
const stats = [
{ icon: <TrophyOutlined />, number: "50+", label: "Projects Completed" },
{ icon: <GlobalOutlined />, number: "25+", label: "Happy Clients" },
{ icon: <TeamOutlined />, number: "15+", label: "Expert Developers" },
{ icon: <RocketOutlined />, number: "3+", label: "Years Experience" },
];
const values = [
{
title: "Innovation First",
description: "We stay ahead of technology trends to deliver cutting-edge solutions that give our clients a competitive advantage.",
icon: <RocketOutlined />
},
{
title: "Quality Excellence",
description: "Every project is crafted with attention to detail, ensuring the highest standards of quality and performance.",
icon: <StarOutlined />
},
{
title: "Client Success",
description: "Your success is our success. We work closely with clients to understand their needs and deliver solutions that exceed expectations.",
icon: <CheckCircleOutlined />
},
{
title: "Transparency",
description: "We believe in open communication and transparent processes, keeping you informed at every step of your project.",
icon: <GlobalOutlined />
}
];
return (
<main className="pt-20">
{/* Hero Section */}
<section className="py-20 bg-gradient-to-br from-[#0F0525] to-[#2A0B45] text-white">
<div className="max-w-6xl mx-auto px-4">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
className="text-center"
>
<Title level={1} className="text-5xl font-bold mb-6 text-white">
About Tech Master
</Title>
<Paragraph className="text-xl text-gray-300 max-w-3xl mx-auto">
From Dubai to the stars, we&apos;re an award-winning technology agency
dedicated to transforming businesses through innovative digital solutions.
</Paragraph>
</motion.div>
</div>
</section>
{/* Stats Section */}
<section className="py-16 bg-white">
<div className="max-w-6xl mx-auto px-4">
<Row gutter={[32, 32]} justify="center">
{stats.map((stat, index) => (
<Col xs={24} sm={12} md={6} key={index}>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: index * 0.1 }}
className="text-center"
>
<div className="text-4xl text-[#6e48aa] mb-2">
{stat.icon}
</div>
<div className="text-3xl font-bold text-gray-800 mb-1">
{stat.number}
</div>
<div className="text-gray-600">{stat.label}</div>
</motion.div>
</Col>
))}
</Row>
</div>
</section>
{/* Story Section */}
<section className="py-16 bg-gray-50">
<div className="max-w-6xl mx-auto px-4">
<Row gutter={[48, 48]} align="middle">
<Col xs={24} lg={12}>
<motion.div
initial={{ opacity: 0, x: -30 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.8 }}
>
<Title level={2} className="text-4xl font-bold mb-6">
Our Story
</Title>
<Paragraph className="text-lg text-gray-700 mb-6">
Founded in 2020, Tech Master emerged from a vision to bridge the gap
between traditional business practices and cutting-edge technology.
Based in Dubai, we&apos;ve grown from a small startup to an award-winning
technology agency serving clients across the UAE and beyond.
</Paragraph>
<Paragraph className="text-lg text-gray-700">
Our journey has been marked by continuous innovation, unwavering
commitment to quality, and a deep understanding of our clients&apos; needs.
We believe that technology should be an enabler, not a barrier,
and we work tirelessly to make digital transformation accessible
to businesses of all sizes.
</Paragraph>
</motion.div>
</Col>
<Col xs={24} lg={12}>
<motion.div
initial={{ opacity: 0, x: 30 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.8 }}
className="text-center"
>
<div className="w-64 h-64 mx-auto bg-gradient-to-br from-[#6e48aa] to-[#9d50bb] rounded-full flex items-center justify-center">
<GlobalOutlined className="text-6xl text-white" />
</div>
</motion.div>
</Col>
</Row>
</div>
</section>
{/* Values Section */}
<section className="py-16 bg-white">
<div className="max-w-6xl mx-auto px-4">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
className="text-center mb-12"
>
<Title level={2} className="text-4xl font-bold mb-4">
Our Values
</Title>
<Paragraph className="text-lg text-gray-600 max-w-2xl mx-auto">
These core values guide everything we do and shape the way we
approach every project and client relationship.
</Paragraph>
</motion.div>
<Row gutter={[32, 32]}>
{values.map((value, index) => (
<Col xs={24} sm={12} lg={6} key={index}>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: index * 0.1 }}
>
<Card className="h-full text-center hover:shadow-lg transition-shadow">
<div className="text-4xl text-[#6e48aa] mb-4">
{value.icon}
</div>
<Title level={4} className="mb-3">
{value.title}
</Title>
<Paragraph className="text-gray-600">
{value.description}
</Paragraph>
</Card>
</motion.div>
</Col>
))}
</Row>
</div>
</section>
{/* Team Section */}
<section className="py-16 bg-gray-50">
<div className="max-w-6xl mx-auto px-4">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
className="text-center mb-12"
>
<Title level={2} className="text-4xl font-bold mb-4">
Our Team
</Title>
<Paragraph className="text-lg text-gray-600 max-w-2xl mx-auto">
Meet the passionate professionals behind Tech Master&apos;s success.
Our diverse team brings together expertise from various domains
to deliver exceptional results.
</Paragraph>
</motion.div>
<Row gutter={[32, 32]} justify="center">
<Col xs={24} sm={12} md={8}>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="text-center"
>
<Avatar size={120} src="https://randomuser.me/api/portraits/men/32.jpg" className="mb-4" />
<Title level={4} className="mb-2">Ahmed Hassan</Title>
<Paragraph className="text-gray-600 mb-2">CEO & Founder</Paragraph>
<Paragraph className="text-sm text-gray-500">
Visionary leader with 10+ years in digital transformation
</Paragraph>
</motion.div>
</Col>
<Col xs={24} sm={12} md={8}>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.1 }}
className="text-center"
>
<Avatar size={120} src="https://randomuser.me/api/portraits/women/44.jpg" className="mb-4" />
<Title level={4} className="mb-2">Sarah Johnson</Title>
<Paragraph className="text-gray-600 mb-2">CTO</Paragraph>
<Paragraph className="text-sm text-gray-500">
Technical expert specializing in AI and cloud solutions
</Paragraph>
</motion.div>
</Col>
<Col xs={24} sm={12} md={8}>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.2 }}
className="text-center"
>
<Avatar size={120} src="https://randomuser.me/api/portraits/men/67.jpg" className="mb-4" />
<Title level={4} className="mb-2">Raj Patel</Title>
<Paragraph className="text-gray-600 mb-2">Lead Developer</Paragraph>
<Paragraph className="text-sm text-gray-500">
Full-stack developer with expertise in modern frameworks
</Paragraph>
</motion.div>
</Col>
</Row>
</div>
</section>
</main>
);
}

View File

@@ -1,30 +1,10 @@
// File: src/components/home/ProjectsShowcase.tsx
import {
CloseOutlined,
EyeOutlined,
GithubOutlined,
LeftOutlined,
LinkOutlined,
RightOutlined,
} from "@ant-design/icons";
import {
Badge,
Button,
Card,
Carousel,
Col,
Modal,
Row,
Tag,
Typography,
Typography
} from "antd";
import { AnimatePresence, motion, useAnimation } from "framer-motion";
import Image from "next/image";
import React, { useEffect, useState } from "react";
import ProjectsShowcaseClient from "./ProjectsShowcaseClient";
import styles from "./ProjectsShowcaseSelector.module.css";
const { Title, Paragraph, Text } = Typography;
const { Title, Paragraph } = Typography;
interface Project {
id: string;
@@ -273,331 +253,20 @@ const projectsData: Project[] = [
];
const ProjectsShowcase: React.FC = () => {
const [currentIndex, setCurrentIndex] = useState(0);
const [visibleProjects, setVisibleProjects] = useState<Project[]>([]);
const [selectedProject, setSelectedProject] = useState<Project | null>(null);
const [isModalVisible, setIsModalVisible] = useState(false);
const controls = useAnimation();
// Determine number of projects to show based on screen width
const [projectsPerView, setProjectsPerView] = useState(3);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth < 768) {
setProjectsPerView(1);
} else if (window.innerWidth < 992) {
setProjectsPerView(2);
} else {
setProjectsPerView(3);
}
};
// Set initial state
handleResize();
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
useEffect(() => {
// Update visible projects whenever currentIndex or projectsPerView changes
setVisibleProjects(
projectsData.slice(currentIndex, currentIndex + projectsPerView)
);
}, [currentIndex, projectsPerView]);
const handleNext = async () => {
if (currentIndex + projectsPerView < projectsData.length) {
await controls.start({
x: "-100%",
opacity: 0,
transition: { duration: 0.3 },
});
setCurrentIndex((prev) => prev + 1);
controls.start({
x: 0,
opacity: 1,
transition: { duration: 0.3 },
});
}
};
const handlePrev = async () => {
if (currentIndex > 0) {
await controls.start({
x: "100%",
opacity: 0,
transition: { duration: 0.3 },
});
setCurrentIndex((prev) => prev - 1);
controls.start({
x: 0,
opacity: 1,
transition: { duration: 0.3 },
});
}
};
const handleProjectClick = (project: Project) => {
setSelectedProject(project);
setIsModalVisible(true);
};
const handleModalClose = () => {
setIsModalVisible(false);
setTimeout(() => {
setSelectedProject(null);
}, 300);
};
return (
<section className={styles.projectsSection}>
<div className={styles.container}>
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
className={styles.sectionHeader}
>
<div className={styles.sectionHeader}>
<Title level={2} className={styles.sectionTitle}>
Our Work
</Title>
<Paragraph className={styles.sectionSubtitle}>
Transforming ideas into powerful digital solutions
</Paragraph>
</motion.div>
<div className={styles.showcaseContainer}>
<motion.div
className={styles.projectsGrid}
animate={controls}
initial={{ opacity: 1, x: 0 }}
>
<Row gutter={[24, 24]}>
{visibleProjects.map((project) => (
<Col xs={24} md={24 / projectsPerView} key={project.id}>
<motion.div
whileHover={{ y: -10 }}
transition={{ type: "spring", stiffness: 300 }}
>
<Card
hoverable
onClick={() => handleProjectClick(project)}
cover={
<div className={styles.projectImageContainer}>
<Image
alt={project.title}
src={project.imageUrl}
className={styles.projectImage}
width={400}
height={400}
/>
<div className={styles.projectOverlay}>
<Button
type="primary"
shape="circle"
icon={<EyeOutlined />}
className={styles.viewButton}
/>
</div>
{project.featured && (
<Badge.Ribbon
text="Featured"
className={styles.featuredBadge}
/>
)}
</div>
}
className={styles.projectCard}
>
<div className={styles.categoryTag}>
<Tag color="blue">{project.category}</Tag>
</div>
<Card.Meta
title={project.title}
description={project.description}
/>
<div className={styles.technologiesList}>
{project.technologies.map((tech) => (
<Tag key={tech} className={styles.techTag}>
{tech}
</Tag>
))}
</div>
</Card>
</motion.div>
</Col>
))}
</Row>
</motion.div>
<div className={styles.navigationControls}>
<Button
shape="circle"
icon={<LeftOutlined />}
onClick={handlePrev}
disabled={currentIndex === 0}
className={styles.navButton}
/>
<Text className={styles.pageIndicator}>
{currentIndex + 1}-
{Math.min(currentIndex + projectsPerView, projectsData.length)} of{" "}
{projectsData.length}
</Text>
<Button
shape="circle"
icon={<RightOutlined />}
onClick={handleNext}
disabled={currentIndex + projectsPerView >= projectsData.length}
className={styles.navButton}
/>
</div>
</div>
<div className={styles.viewAllContainer}>
<Button type="primary" size="large" className={styles.viewAllButton}>
View All Projects
</Button>
</div>
<ProjectsShowcaseClient projects={projectsData} />
</div>
{/* Project Details Modal */}
<AnimatePresence>
{isModalVisible && selectedProject && (
<Modal
open={isModalVisible}
onCancel={handleModalClose}
footer={null}
width={1000}
className={styles.projectModal}
closeIcon={<CloseOutlined className={styles.closeIcon} />}
>
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ duration: 0.3 }}
className={styles.modalContent}
>
<div className={styles.modalHeader}>
<div className={styles.modalTitleSection}>
<Title level={2} className={styles.modalTitle}>
{selectedProject.title}
</Title>
<Tag color="blue" className={styles.modalCategory}>
{selectedProject.category}
</Tag>
</div>
<div className={styles.modalActions}>
{selectedProject.liveUrl && (
<Button
type="primary"
icon={<LinkOutlined />}
href={selectedProject.liveUrl}
target="_blank"
className={styles.actionButton}
>
Live Demo
</Button>
)}
{selectedProject.githubUrl && (
<Button
icon={<GithubOutlined />}
href={selectedProject.githubUrl}
target="_blank"
className={styles.actionButton}
>
View Code
</Button>
)}
</div>
</div>
<div className={styles.modalBody}>
<div className={styles.projectImages}>
<Carousel
autoplay
dots={{ className: styles.carouselDots }}
className={styles.imageCarousel}
>
{selectedProject.images.map((image, index) => (
<div key={index} className={styles.carouselItem}>
<Image
src={image}
alt={`${selectedProject.title} - Image ${index + 1}`}
width={800}
height={500}
className={styles.modalImage}
/>
</div>
))}
</Carousel>
</div>
<div className={styles.projectDetails}>
<div className={styles.detailSection}>
<Title level={4} className={styles.sectionTitle}>
Project Overview
</Title>
<Paragraph className={styles.projectDescription}>
{selectedProject.detailedDescription}
</Paragraph>
</div>
<div className={styles.detailGrid}>
<div className={styles.detailSection}>
<Title level={4} className={styles.sectionTitle}>
Key Features
</Title>
<ul className={styles.featuresList}>
{selectedProject.features.map((feature, index) => (
<motion.li
key={index}
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: index * 0.1 }}
className={styles.featureItem}
>
{feature}
</motion.li>
))}
</ul>
</div>
<div className={styles.detailSection}>
<Title level={4} className={styles.sectionTitle}>
Project Details
</Title>
<div className={styles.projectInfo}>
<div className={styles.infoItem}>
<Text strong>Duration:</Text>
<Text>{selectedProject.duration}</Text>
</div>
<div className={styles.infoItem}>
<Text strong>Team Size:</Text>
<Text>{selectedProject.teamSize}</Text>
</div>
<div className={styles.infoItem}>
<Text strong>Technologies:</Text>
<div className={styles.modalTechnologies}>
{selectedProject.technologies.map((tech) => (
<Tag key={tech} className={styles.modalTechTag}>
{tech}
</Tag>
))}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</motion.div>
</Modal>
)}
</AnimatePresence>
</section>
);
};

View File

@@ -0,0 +1,365 @@
"use client";
import {
CloseOutlined,
EyeOutlined,
GithubOutlined,
LeftOutlined,
LinkOutlined,
RightOutlined,
} from "@ant-design/icons";
import {
Badge,
Button,
Card,
Carousel,
Col,
Modal,
Row,
Tag,
Typography,
} from "antd";
import { AnimatePresence, motion, useAnimation } from "framer-motion";
import Image from "next/image";
import React, { useEffect, useState } from "react";
import styles from "./ProjectsShowcaseSelector.module.css";
const { Title, Paragraph, Text } = Typography;
interface Project {
id: string;
title: string;
description: string;
imageUrl: string;
category: string;
technologies: string[];
featured: boolean;
detailedDescription: string;
images: string[];
liveUrl?: string;
githubUrl?: string;
features: string[];
duration: string;
teamSize: string;
}
interface ProjectsShowcaseClientProps {
projects: Project[];
}
const ProjectsShowcaseClient: React.FC<ProjectsShowcaseClientProps> = ({
projects,
}) => {
const [currentIndex, setCurrentIndex] = useState(0);
const [visibleProjects, setVisibleProjects] = useState<Project[]>([]);
const [selectedProject, setSelectedProject] = useState<Project | null>(null);
const [isModalVisible, setIsModalVisible] = useState(false);
const controls = useAnimation();
// Determine number of projects to show based on screen width
const [projectsPerView, setProjectsPerView] = useState(3);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth < 768) {
setProjectsPerView(1);
} else if (window.innerWidth < 992) {
setProjectsPerView(2);
} else {
setProjectsPerView(3);
}
};
// Set initial state
handleResize();
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
useEffect(() => {
// Update visible projects whenever currentIndex or projectsPerView changes
setVisibleProjects(
projects.slice(currentIndex, currentIndex + projectsPerView)
);
}, [currentIndex, projectsPerView, projects]);
const handleNext = async () => {
if (currentIndex + projectsPerView < projects.length) {
await controls.start({
x: "-100%",
opacity: 0,
transition: { duration: 0.3 },
});
setCurrentIndex((prev) => prev + 1);
controls.start({
x: 0,
opacity: 1,
transition: { duration: 0.3 },
});
}
};
const handlePrev = async () => {
if (currentIndex > 0) {
await controls.start({
x: "100%",
opacity: 0,
transition: { duration: 0.3 },
});
setCurrentIndex((prev) => prev - 1);
controls.start({
x: 0,
opacity: 1,
transition: { duration: 0.3 },
});
}
};
const handleProjectClick = (project: Project) => {
setSelectedProject(project);
setIsModalVisible(true);
};
const handleModalClose = () => {
setIsModalVisible(false);
setTimeout(() => {
setSelectedProject(null);
}, 300);
};
return (
<>
<div className={styles.showcaseContainer}>
<motion.div
className={styles.projectsGrid}
animate={controls}
initial={{ opacity: 1, x: 0 }}
>
<Row gutter={[24, 24]}>
{visibleProjects.map((project) => (
<Col xs={24} md={24 / projectsPerView} key={project.id}>
<motion.div
whileHover={{ y: -10 }}
transition={{ type: "spring", stiffness: 300 }}
>
<Card
hoverable
onClick={() => handleProjectClick(project)}
cover={
<div className={styles.projectImageContainer}>
<Image
alt={project.title}
src={project.imageUrl}
className={styles.projectImage}
width={400}
height={400}
/>
<div className={styles.projectOverlay}>
<Button
type="primary"
shape="circle"
icon={<EyeOutlined />}
className={styles.viewButton}
/>
</div>
{project.featured && (
<Badge.Ribbon
text="Featured"
className={styles.featuredBadge}
/>
)}
</div>
}
className={styles.projectCard}
>
<div className={styles.categoryTag}>
<Tag color="blue">{project.category}</Tag>
</div>
<Card.Meta
title={project.title}
description={project.description}
/>
<div className={styles.technologiesList}>
{project.technologies.map((tech) => (
<Tag key={tech} className={styles.techTag}>
{tech}
</Tag>
))}
</div>
</Card>
</motion.div>
</Col>
))}
</Row>
</motion.div>
<div className={styles.navigationControls}>
<Button
shape="circle"
icon={<LeftOutlined />}
onClick={handlePrev}
disabled={currentIndex === 0}
className={styles.navButton}
/>
<Text className={styles.pageIndicator}>
{currentIndex + 1}-
{Math.min(currentIndex + projectsPerView, projects.length)} of{" "}
{projects.length}
</Text>
<Button
shape="circle"
icon={<RightOutlined />}
onClick={handleNext}
disabled={currentIndex + projectsPerView >= projects.length}
className={styles.navButton}
/>
</div>
</div>
<div className={styles.viewAllContainer}>
<Button type="primary" size="large" className={styles.viewAllButton}>
View All Projects
</Button>
</div>
{/* Project Details Modal */}
<AnimatePresence>
{isModalVisible && selectedProject && (
<Modal
open={isModalVisible}
onCancel={handleModalClose}
footer={null}
width={1000}
className={styles.projectModal}
closeIcon={<CloseOutlined className={styles.closeIcon} />}
>
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ duration: 0.3 }}
className={styles.modalContent}
>
<div className={styles.modalHeader}>
<div className={styles.modalTitleSection}>
<Title level={2} className={styles.modalTitle}>
{selectedProject.title}
</Title>
<Tag color="blue" className={styles.modalCategory}>
{selectedProject.category}
</Tag>
</div>
<div className={styles.modalActions}>
{selectedProject.liveUrl && (
<Button
type="primary"
icon={<LinkOutlined />}
href={selectedProject.liveUrl}
target="_blank"
className={styles.actionButton}
>
Live Demo
</Button>
)}
{selectedProject.githubUrl && (
<Button
icon={<GithubOutlined />}
href={selectedProject.githubUrl}
target="_blank"
className={styles.actionButton}
>
View Code
</Button>
)}
</div>
</div>
<div className={styles.modalBody}>
<div className={styles.projectImages}>
<Carousel
autoplay
dots={{ className: styles.carouselDots }}
className={styles.imageCarousel}
>
{selectedProject.images.map((image, index) => (
<div key={index} className={styles.carouselItem}>
<Image
src={image}
alt={`${selectedProject.title} - Image ${index + 1}`}
width={800}
height={500}
className={styles.modalImage}
/>
</div>
))}
</Carousel>
</div>
<div className={styles.projectDetails}>
<div className={styles.detailSection}>
<Title level={4} className={styles.sectionTitle}>
Project Overview
</Title>
<Paragraph className={styles.projectDescription}>
{selectedProject.detailedDescription}
</Paragraph>
</div>
<div className={styles.detailGrid}>
<div className={styles.detailSection}>
<Title level={4} className={styles.sectionTitle}>
Key Features
</Title>
<ul className={styles.featuresList}>
{selectedProject.features.map((feature, index) => (
<motion.li
key={index}
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: index * 0.1 }}
className={styles.featureItem}
>
{feature}
</motion.li>
))}
</ul>
</div>
<div className={styles.detailSection}>
<Title level={4} className={styles.sectionTitle}>
Project Details
</Title>
<div className={styles.projectInfo}>
<div className={styles.infoItem}>
<Text strong>Duration:</Text>
<Text>{selectedProject.duration}</Text>
</div>
<div className={styles.infoItem}>
<Text strong>Team Size:</Text>
<Text>{selectedProject.teamSize}</Text>
</div>
<div className={styles.infoItem}>
<Text strong>Technologies:</Text>
<div className={styles.modalTechnologies}>
{selectedProject.technologies.map((tech) => (
<Tag key={tech} className={styles.modalTechTag}>
{tech}
</Tag>
))}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</motion.div>
</Modal>
)}
</AnimatePresence>
</>
);
};
export default ProjectsShowcaseClient;

View File

@@ -0,0 +1,32 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Contact Us | Tech Master - Get In Touch for IT Solutions",
description: "Contact Tech Master in Dubai for innovative IT solutions, digital transformation, web development, and mobile app development. Start your project today.",
keywords: [
"contact Tech Master",
"Dubai IT company contact",
"web development Dubai contact",
"digital transformation consultation",
"IT solutions contact",
"mobile app development Dubai",
"enterprise software consultation",
"tech agency Dubai contact"
],
openGraph: {
title: "Contact Us | Tech Master - Get In Touch for IT Solutions",
description: "Contact Tech Master in Dubai for innovative IT solutions, digital transformation, and mobile app development.",
url: "https://tech-masters.guru/contact",
},
alternates: {
canonical: "/contact",
},
};
export default function ContactLayout({
children,
}: {
children: React.ReactNode;
}) {
return children;
}

11
src/app/contact/page.tsx Normal file
View File

@@ -0,0 +1,11 @@
"use client";
import ContactSection from "../components/Contact/Contact";
export default function ContactPage() {
return (
<main className="pt-20">
<ContactSection />
</main>
);
}

View File

@@ -17,7 +17,78 @@ const inter = Inter({
});
export const metadata: Metadata = {
title: "Tech Master | Dubai To Stars",
title: "Tech Master | Dubai To Stars - Award-Winning IT Solutions",
description: "Tech Master is an award-winning Dubai-based technology agency specializing in digital transformation, web development, mobile apps, AI solutions, and enterprise software. From zero to hero, we create cutting-edge digital experiences for ambitious businesses.",
keywords: [
"Dubai IT solutions",
"digital transformation",
"web development Dubai",
"mobile app development",
"AI solutions",
"enterprise software",
"ERP systems",
"e-commerce development",
"financial solutions",
"legal software",
"business intelligence",
"cloud migration",
"cybersecurity",
"blockchain development",
"IoT solutions",
"tech agency Dubai",
"software development UAE"
],
authors: [{ name: "Tech Master" }],
creator: "Tech Master",
publisher: "Tech Master",
formatDetection: {
email: false,
address: false,
telephone: false,
},
metadataBase: new URL("https://tech-masters.guru"),
alternates: {
canonical: "/",
},
openGraph: {
title: "Tech Master | Dubai To Stars - Award-Winning IT Solutions",
description: "Award-winning Dubai-based technology agency specializing in digital transformation, web development, mobile apps, AI solutions, and enterprise software.",
url: "https://tech-masters.guru",
siteName: "Tech Master",
images: [
{
url: "https://tech-masters.guru/og-image.jpg",
width: 1200,
height: 630,
alt: "Tech Master - Dubai To Stars",
},
],
locale: "en_US",
type: "website",
},
twitter: {
card: "summary_large_image",
title: "Tech Master | Dubai To Stars - Award-Winning IT Solutions",
description: "Award-winning Dubai-based technology agency specializing in digital transformation and innovative IT solutions.",
images: ["https://tech-masters.guru/twitter-image.jpg"],
creator: "@techmasterdubai",
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
"max-video-preview": -1,
"max-image-preview": "large",
"max-snippet": -1,
},
},
verification: {
google: "your-google-verification-code",
yandex: "your-yandex-verification-code",
yahoo: "your-yahoo-verification-code",
},
};
export default function RootLayout({
@@ -37,7 +108,36 @@ export default function RootLayout({
src="https://threejs.org/examples/js/libs/stats.min.js"
async
></script>
{/* Orbitron Font */}
{/* Structured Data */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "Organization",
"name": "Tech Master",
"url": "https://tech-masters.guru",
"logo": "https://tech-masters.guru/logo.png",
"description": "Award-winning Dubai-based technology agency specializing in digital transformation and innovative IT solutions.",
"address": {
"@type": "PostalAddress",
"addressLocality": "Dubai",
"addressCountry": "UAE"
},
"contactPoint": {
"@type": "ContactPoint",
"telephone": "+971-XX-XXX-XXXX",
"contactType": "customer service"
},
"sameAs": [
"https://linkedin.com/company/tech-master",
"https://twitter.com/techmasterdubai",
"https://facebook.com/techmasterdubai"
]
})
}}
/>
</head>
<body
className={`${inter.className} bg-gradient-to-br from-[#0F0525] to-[#2A0B45]`}

View File

@@ -61,11 +61,25 @@ export default function Home() {
)}
<main className={styles.main}>
<HeroSection />
<ServicesSection userPreferences={userPreferences} />
<ProjectsShowcase />
<TestimonialsSection />
<ContactSection />
<section id="home">
<HeroSection />
</section>
<section id="services">
<ServicesSection userPreferences={userPreferences} />
</section>
<section id="projects">
<ProjectsShowcase />
</section>
<section id="testimonials">
<TestimonialsSection />
</section>
<section id="contact">
<ContactSection />
</section>
</main>
</>
);

View File

@@ -0,0 +1,34 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Our Projects | Tech Master - Portfolio of Digital Solutions",
description: "Explore our portfolio of successful projects including ERP systems, e-commerce platforms, payment solutions, legal software, and business intelligence dashboards developed in Dubai.",
keywords: [
"portfolio projects",
"ERP systems Dubai",
"e-commerce development",
"payment platforms",
"legal software",
"business intelligence",
"web applications",
"mobile apps",
"enterprise software",
"fintech solutions"
],
openGraph: {
title: "Our Projects | Tech Master - Portfolio of Digital Solutions",
description: "Portfolio of successful projects including ERP systems, e-commerce platforms, payment solutions, and business intelligence dashboards.",
url: "https://tech-masters.guru/projects",
},
alternates: {
canonical: "/projects",
},
};
export default function ProjectsLayout({
children,
}: {
children: React.ReactNode;
}) {
return children;
}

View File

@@ -0,0 +1,9 @@
import ProjectsShowcase from "../components/ProjectsShowcase/ProjectsShowcase";
export default function ProjectsPage() {
return (
<main className="pt-20">
<ProjectsShowcase />
</main>
);
}

12
src/app/robots.ts Normal file
View File

@@ -0,0 +1,12 @@
import { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: '*',
allow: '/',
disallow: '/private/',
},
sitemap: 'https://tech-masters.guru/sitemap.xml',
}
}

View File

@@ -0,0 +1,33 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Our Services | Tech Master - Digital Transformation & IT Solutions",
description: "Explore our comprehensive IT services including web development, mobile apps, AI solutions, ERP systems, e-commerce platforms, and digital transformation services in Dubai.",
keywords: [
"web development Dubai",
"mobile app development",
"AI solutions",
"ERP systems",
"e-commerce development",
"digital transformation",
"cloud migration",
"cybersecurity services",
"IT consulting Dubai"
],
openGraph: {
title: "Our Services | Tech Master - Digital Transformation & IT Solutions",
description: "Comprehensive IT services including web development, mobile apps, AI solutions, ERP systems, and digital transformation in Dubai.",
url: "https://tech-masters.guru/services",
},
alternates: {
canonical: "/services",
},
};
export default function ServicesLayout({
children,
}: {
children: React.ReactNode;
}) {
return children;
}

11
src/app/services/page.tsx Normal file
View File

@@ -0,0 +1,11 @@
"use client";
import ServicesSection from "../components/Services/Services";
export default function ServicesPage() {
return (
<main className="pt-20">
<ServicesSection userPreferences={[]} />
</main>
);
}

44
src/app/sitemap.ts Normal file
View File

@@ -0,0 +1,44 @@
import { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap {
const baseUrl = 'https://tech-masters.guru'
return [
{
url: baseUrl,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 1,
},
{
url: `${baseUrl}/about`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: `${baseUrl}/services`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: `${baseUrl}/projects`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.9,
},
{
url: `${baseUrl}/testimonials`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.7,
},
{
url: `${baseUrl}/contact`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
]
}

View File

@@ -0,0 +1,32 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Client Testimonials | Tech Master - What Our Clients Say",
description: "Read testimonials from our satisfied clients in Dubai. Discover how Tech Master has helped businesses achieve digital transformation and success through innovative IT solutions.",
keywords: [
"client testimonials",
"customer reviews",
"Dubai IT company reviews",
"digital transformation success",
"IT solutions testimonials",
"web development reviews",
"mobile app development feedback",
"enterprise software testimonials"
],
openGraph: {
title: "Client Testimonials | Tech Master - What Our Clients Say",
description: "Read testimonials from our satisfied clients in Dubai. Discover how Tech Master has helped businesses achieve digital transformation.",
url: "https://tech-masters.guru/testimonials",
},
alternates: {
canonical: "/testimonials",
},
};
export default function TestimonialsLayout({
children,
}: {
children: React.ReactNode;
}) {
return children;
}

View File

@@ -0,0 +1,11 @@
"use client";
import TestimonialsSection from "../components/Testimonials/Testimonials";
export default function TestimonialsPage() {
return (
<main className="pt-20">
<TestimonialsSection />
</main>
);
}