{
"name": "securiace-website",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"lint:fix": "next lint --fix",
"type-check": "tsc --noEmit",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"test:e2e": "playwright test",
"lighthouse": "lighthouse http://localhost:3000 --output=html --output-path=./lighthouse-report.html",
"analyze": "cross-env ANALYZE=true next build",
"format": "prettier --write .",
"format:check": "prettier --check .",
"prepare": "husky install"
},
"dependencies": {
"next": "14.0.4",
"react": "18.2.0",
"react-dom": "18.2.0",
"typescript": "5.3.3",
"@types/node": "20.10.5",
"@types/react": "18.2.45",
"@types/react-dom": "18.2.18",
"tailwindcss": "3.3.6",
"autoprefixer": "10.4.16",
"postcss": "8.4.32",
"@tailwindcss/typography": "0.5.10",
"@tailwindcss/forms": "0.5.7",
"class-variance-authority": "0.7.0",
"clsx": "2.0.0",
"tailwind-merge": "2.2.0",
"lucide-react": "0.294.0",
"framer-motion": "10.16.16",
"lottie-react": "2.4.0",
"react-hook-form": "7.48.2",
"@hookform/resolvers": "3.3.2",
"zod": "3.22.4",
"zustand": "4.4.7",
"@tanstack/react-query": "5.14.2",
"react-intersection-observer": "9.5.3",
"next-themes": "0.2.1",
"next-seo": "6.4.0",
"sharp": "0.33.1"
},
"devDependencies": {
"eslint": "8.56.0",
"eslint-config-next": "14.0.4",
"@typescript-eslint/eslint-plugin": "6.15.0",
"@typescript-eslint/parser": "6.15.0",
"prettier": "3.1.1",
"prettier-plugin-tailwindcss": "0.5.9",
"husky": "8.0.3",
"lint-staged": "15.2.0",
"jest": "29.7.0",
"@testing-library/react": "14.1.2",
"@testing-library/jest-dom": "6.1.6",
"jest-environment-jsdom": "29.7.0",
"@playwright/test": "1.40.1",
"lighthouse": "11.4.0",
"@next/bundle-analyzer": "14.0.4",
"cross-env": "7.0.3"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{json,md,yml,yaml}": ["prettier --write"]
}
}/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
appDir: true,
},
images: {
formats: ['image/webp', 'image/avif'],
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
minimumCacheTTL: 60,
dangerouslyAllowSVG: true,
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
},
async headers() {
return [
{
source: '/(.*)',
headers: [
{
key: 'X-DNS-Prefetch-Control',
value: 'on',
},
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload',
},
{
key: 'X-XSS-Protection',
value: '1; mode=block',
},
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN',
},
{
key: 'X-Content-Type-Options',
value: 'nosniff',
},
{
key: 'Referrer-Policy',
value: 'origin-when-cross-origin',
},
{
key: 'Content-Security-Policy',
value:
"default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https:;",
},
],
},
];
},
async redirects() {
return [
{
source: '/home',
destination: '/',
permanent: true,
},
];
},
};
module.exports = nextConfig;/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ['class'],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
],
theme: {
container: {
center: true,
padding: '2rem',
screens: {
'2xl': '1400px',
},
},
extend: {
colors: {
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))',
50: '#f0f9ff',
100: '#e0f2fe',
200: '#bae6fd',
300: '#7dd3fc',
400: '#38bdf8',
500: '#0ea5e9',
600: '#0284c7',
700: '#0369a1',
800: '#075985',
900: '#0c4a6e',
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))',
50: '#f0fdf4',
100: '#dcfce7',
200: '#bbf7d0',
300: '#86efac',
400: '#4ade80',
500: '#22c55e',
600: '#16a34a',
700: '#15803d',
800: '#166534',
900: '#14532d',
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))',
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))',
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))',
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))',
},
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))',
},
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)',
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace'],
},
keyframes: {
'accordion-down': {
from: { height: 0 },
to: { height: 'var(--radix-accordion-content-height)' },
},
'accordion-up': {
from: { height: 'var(--radix-accordion-content-height)' },
to: { height: 0 },
},
'fade-in': {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
'fade-in-up': {
'0%': { opacity: '0', transform: 'translateY(20px)' },
'100%': { opacity: '1', transform: 'translateY(0)' },
},
'slide-in-left': {
'0%': { opacity: '0', transform: 'translateX(-20px)' },
'100%': { opacity: '1', transform: 'translateX(0)' },
},
'slide-in-right': {
'0%': { opacity: '0', transform: 'translateX(20px)' },
'100%': { opacity: '1', transform: 'translateX(0)' },
},
'scale-in': {
'0%': { opacity: '0', transform: 'scale(0.9)' },
'100%': { opacity: '1', transform: 'scale(1)' },
},
},
animation: {
'accordion-down': 'accordion-down 0.2s ease-out',
'accordion-up': 'accordion-up 0.2s ease-out',
'fade-in': 'fade-in 0.5s ease-out',
'fade-in-up': 'fade-in-up 0.6s ease-out',
'slide-in-left': 'slide-in-left 0.6s ease-out',
'slide-in-right': 'slide-in-right 0.6s ease-out',
'scale-in': 'scale-in 0.4s ease-out',
},
},
},
plugins: [require('@tailwindcss/typography'), require('@tailwindcss/forms')],
};{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "es6"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@/components/*": ["./src/components/*"],
"@/lib/*": ["./src/lib/*"],
"@/hooks/*": ["./src/hooks/*"],
"@/types/*": ["./src/types/*"],
"@/styles/*": ["./src/styles/*"],
"@/content/*": ["./src/content/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}// src/components/ui/button.tsx
import * as React from 'react';
import { Slot } from '@radix-ui/react-slot';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils';
const buttonVariants = cva(
'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
default: 'h-10 px-4 py-2',
sm: 'h-9 rounded-md px-3',
lg: 'h-11 rounded-md px-8',
icon: 'h-10 w-10',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
}
);
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : 'button';
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
);
}
);
Button.displayName = 'Button';
export { Button, buttonVariants };// src/components/ui/card.tsx
import * as React from 'react';
import { cn } from '@/lib/utils';
const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
'rounded-lg border bg-card text-card-foreground shadow-sm',
className
)}
{...props}
/>
));
Card.displayName = 'Card';
const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn('flex flex-col space-y-1.5 p-6', className)}
{...props}
/>
));
CardHeader.displayName = 'CardHeader';
const CardTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h3
ref={ref}
className={cn(
'text-2xl font-semibold leading-none tracking-tight',
className
)}
{...props}
/>
));
CardTitle.displayName = 'CardTitle';
const CardDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<p
ref={ref}
className={cn('text-sm text-muted-foreground', className)}
{...props}
/>
));
CardDescription.displayName = 'CardDescription';
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
));
CardContent.displayName = 'CardContent';
const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn('flex items-center p-6 pt-0', className)}
{...props}
/>
));
CardFooter.displayName = 'CardFooter';
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };// src/components/ui/input.tsx
import * as React from 'react';
import { cn } from '@/lib/utils';
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className
)}
ref={ref}
{...props}
/>
);
}
);
Input.displayName = 'Input';
export { Input };// src/app/page.tsx
import { Metadata } from 'next';
import { HeroSection } from '@/components/sections/hero/hero-section';
import { ServicesOverview } from '@/components/sections/services/services-overview';
import { TestimonialsSection } from '@/components/sections/testimonials/testimonials-section';
import { CTASection } from '@/components/sections/cta/cta-section';
import { generateMetadata } from '@/lib/seo';
export const metadata: Metadata = generateMetadata({
title: 'Secure, Reliable, Managed Hosting & IT Solutions',
description: 'Enterprise-grade hosting with 99.9% uptime guarantee, advanced security, and 24/7 expert support. Trusted by businesses worldwide.',
keywords: ['web hosting', 'cloud hosting', 'VPS hosting', 'cybersecurity', 'managed IT services'],
canonical: '/',
});
export default function HomePage() {
return (
<main>
<HeroSection />
<ServicesOverview />
<TestimonialsSection />
<CTASection />
</main>
);
}// src/app/services/[slug]/page.tsx
import { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { ServiceHero } from '@/components/sections/services/service-hero';
import { ServiceFeatures } from '@/components/sections/services/service-features';
import { ServicePricing } from '@/components/sections/services/service-pricing';
import { ServiceFAQ } from '@/components/sections/services/service-faq';
import { CTASection } from '@/components/sections/cta/cta-section';
import { generateMetadata } from '@/lib/seo';
import { getServiceBySlug } from '@/lib/services';
interface ServicePageProps {
params: {
slug: string;
};
}
export async function generateMetadata({ params }: ServicePageProps): Promise<Metadata> {
const service = await getServiceBySlug(params.slug);
if (!service) {
return generateMetadata({
title: 'Service Not Found',
description: 'The requested service could not be found.',
noIndex: true,
});
}
return generateMetadata({
title: service.name,
description: service.description,
keywords: service.keywords,
canonical: `/services/${params.slug}`,
});
}
export default async function ServicePage({ params }: ServicePageProps) {
const service = await getServiceBySlug(params.slug);
if (!service) {
notFound();
}
return (
<main>
<ServiceHero service={service} />
<ServiceFeatures features={service.features} />
<ServicePricing pricing={service.pricing} />
<ServiceFAQ faqs={service.faqs} />
<CTASection />
</main>
);
}// src/app/blog/[slug]/page.tsx
import { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { MDXRemote } from 'next-mdx-remote/rsc';
import { BlogHero } from '@/components/sections/blog/blog-hero';
import { BlogContent } from '@/components/sections/blog/blog-content';
import { BlogNavigation } from '@/components/sections/blog/blog-navigation';
import { generateMetadata } from '@/lib/seo';
import { getBlogPostBySlug, getRelatedPosts } from '@/lib/blog';
interface BlogPostPageProps {
params: {
slug: string;
};
}
export async function generateMetadata({ params }: BlogPostPageProps): Promise<Metadata> {
const post = await getBlogPostBySlug(params.slug);
if (!post) {
return generateMetadata({
title: 'Post Not Found',
description: 'The requested blog post could not be found.',
noIndex: true,
});
}
return generateMetadata({
title: post.title,
description: post.excerpt,
keywords: post.keywords,
canonical: `/blog/${params.slug}`,
ogImage: post.featuredImage,
});
}
export default async function BlogPostPage({ params }: BlogPostPageProps) {
const post = await getBlogPostBySlug(params.slug);
const relatedPosts = await getRelatedPosts(params.slug);
if (!post) {
notFound();
}
return (
<main>
<BlogHero post={post} />
<BlogContent content={post.content} />
<BlogNavigation relatedPosts={relatedPosts} />
</main>
);
}// src/lib/utils.ts
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export function formatPrice(price: number, currency: string = 'INR'): string {
return new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: currency,
}).format(price);
}
export function formatDate(date: string | Date): string {
return new Intl.DateTimeFormat('en-IN', {
year: 'numeric',
month: 'long',
day: 'numeric',
}).format(new Date(date));
}
export function slugify(text: string): string {
return text
.toLowerCase()
.replace(/[^\w\s-]/g, '')
.replace(/[\s_-]+/g, '-')
.replace(/^-+|-+$/g, '');
}
export function truncateText(text: string, maxLength: number): string {
if (text.length <= maxLength) return text;
return text.slice(0, maxLength).trim() + '...';
}
export function debounce<T extends (...args: any[]) => any>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: NodeJS.Timeout;
return (...args: Parameters<T>) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), wait);
};
}
export function throttle<T extends (...args: any[]) => any>(
func: T,
limit: number
): (...args: Parameters<T>) => void {
let inThrottle: boolean;
return (...args: Parameters<T>) => {
if (!inThrottle) {
func(...args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}// src/lib/validations.ts
import { z } from 'zod';
export const contactFormSchema = z.object({
name: z.string().min(2, 'Name must be at least 2 characters'),
email: z.string().email('Invalid email address'),
phone: z.string().optional(),
company: z.string().optional(),
service: z.string().min(1, 'Please select a service'),
message: z.string().min(10, 'Message must be at least 10 characters'),
});
export const newsletterSchema = z.object({
email: z.string().email('Invalid email address'),
name: z.string().optional(),
});
export const domainSearchSchema = z.object({
domain: z.string().min(1, 'Please enter a domain name'),
tld: z.string().optional(),
});
export const pricingQuerySchema = z.object({
service: z.string().min(1, 'Please select a service'),
billing: z.enum(['monthly', 'annually', 'biennially']).default('monthly'),
});
export type ContactFormData = z.infer<typeof contactFormSchema>;
export type NewsletterData = z.infer<typeof newsletterSchema>;
export type DomainSearchData = z.infer<typeof domainSearchSchema>;
export type PricingQueryData = z.infer<typeof pricingQuerySchema>;// src/types/api.ts
export interface ApiResponse<T = any> {
success: boolean;
data?: T;
error?: string;
message?: string;
}
export interface PaginatedResponse<T> extends ApiResponse<T[]> {
pagination: {
page: number;
limit: number;
total: number;
totalPages: number;
};
}
export interface Service {
id: string;
name: string;
slug: string;
description: string;
shortDescription: string;
features: string[];
pricing: {
monthly: number;
annually: number;
biennially: number;
};
popular: boolean;
category: string;
keywords: string[];
faqs: FAQ[];
}
export interface FAQ {
question: string;
answer: string;
}
export interface BlogPost {
id: string;
title: string;
slug: string;
excerpt: string;
content: string;
featuredImage: string;
author: {
name: string;
avatar: string;
bio: string;
};
publishedAt: string;
updatedAt: string;
tags: string[];
keywords: string[];
readingTime: number;
}
export interface Testimonial {
id: string;
name: string;
company: string;
role: string;
avatar: string;
content: string;
rating: number;
featured: boolean;
}// jest.setup.js
import '@testing-library/jest-dom';
// Mock Next.js router
jest.mock('next/router', () => ({
useRouter() {
return {
route: '/',
pathname: '/',
query: {},
asPath: '/',
push: jest.fn(),
pop: jest.fn(),
reload: jest.fn(),
back: jest.fn(),
prefetch: jest.fn().mockResolvedValue(undefined),
beforePopState: jest.fn(),
events: {
on: jest.fn(),
off: jest.fn(),
emit: jest.fn(),
},
};
},
}));
// Mock Next.js Image
jest.mock('next/image', () => ({
__esModule: true,
default: props => {
// eslint-disable-next-line @next/next/no-img-element
return <img {...props} />;
},
}));
// Mock Framer Motion
jest.mock('framer-motion', () => ({
motion: {
div: 'div',
span: 'span',
h1: 'h1',
h2: 'h2',
h3: 'h3',
p: 'p',
button: 'button',
},
AnimatePresence: ({ children }) => children,
}));// src/components/__tests__/button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from '../ui/button';
describe('Button Component', () => {
it('renders with default props', () => {
render(<Button>Click me</Button>);
expect(screen.getByRole('button')).toBeInTheDocument();
expect(screen.getByText('Click me')).toBeInTheDocument();
});
it('applies variant classes correctly', () => {
render(<Button variant="outline">Outline Button</Button>);
const button = screen.getByRole('button');
expect(button).toHaveClass('border border-input bg-background');
});
it('applies size classes correctly', () => {
render(<Button size="lg">Large Button</Button>);
const button = screen.getByRole('button');
expect(button).toHaveClass('h-11 rounded-md px-8');
});
it('handles click events', () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click me</Button>);
fireEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
it('is disabled when disabled prop is true', () => {
render(<Button disabled>Disabled Button</Button>);
const button = screen.getByRole('button');
expect(button).toBeDisabled();
});
});// tests/e2e/homepage.spec.ts
import { test, expect } from '@playwright/test';
test.describe('Homepage', () => {
test('should load homepage successfully', async ({ page }) => {
await page.goto('/');
// Check if the page loads
await expect(page).toHaveTitle(/Securiace Technologies/);
// Check if hero section is visible
await expect(page.locator('h1')).toContainText('Secure, Reliable, Managed');
// Check if CTA buttons are present
await expect(
page.locator('button:has-text("Start Hosting Now")')
).toBeVisible();
await expect(page.locator('button:has-text("Get Free SSL")')).toBeVisible();
});
test('should navigate to services page', async ({ page }) => {
await page.goto('/');
// Click on services link
await page.click('a[href="/services"]');
// Check if we're on the services page
await expect(page).toHaveURL('/services');
await expect(page.locator('h1')).toContainText('Our Services');
});
test('should submit contact form', async ({ page }) => {
await page.goto('/contact');
// Fill out the form
await page.fill('input[name="name"]', 'John Doe');
await page.fill('input[name="email"]', 'john@example.com');
await page.fill('select[name="service"]', 'Shared Hosting');
await page.fill(
'textarea[name="message"]',
'I am interested in your hosting services.'
);
// Submit the form
await page.click('button[type="submit"]');
// Check for success message
await expect(page.locator('text=Thank You!')).toBeVisible();
});
});This comprehensive code template collection provides the Cursor AI agent with production-ready code examples and templates for building the Securiace Technologies website with enterprise-grade quality and performance.