Customization Guide
Complete guide for customizing your Modello template - from colors and fonts to components and pages.
Customization Overview
Modello templates are built with customization in mind. Using modern technologies like Next.js, Tailwind CSS, and TypeScript, you can easily modify every aspect of your template to match your brand and requirements.
Design System Approach
All templates follow a consistent design system with reusable components, making customization predictable and maintainable.
Project Structure
Understanding the project structure helps you navigate and customize your template effectively:
your-template/
├── app/ # Next.js App Router pages
│ ├── globals.css # Global styles
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Homepage
│ └── [other-pages]/ # Additional pages
├── components/ # Reusable components
│ ├── ui/ # Base UI components
│ └── [feature-components]/ # Feature-specific components
├── lib/ # Utility functions
│ ├── utils.ts # General utilities
│ └── [other-utils]/ # Specific utilities
├── public/ # Static assets
│ ├── images/ # Images and graphics
│ └── icons/ # Icons and favicons
├── styles/ # Additional stylesheets (if any)
├── tailwind.config.ts # Tailwind configuration
├── next.config.mjs # Next.js configuration
└── package.json # Dependencies and scripts
Tailwind CSS Customization
Tailwind CSS powers the styling system in all Modello templates. Customize the design system by modifying the tailwind.config.ts
file.
Colors & Typography
Customize your brand colors and typography in the Tailwind config:
// tailwind.config.ts
import type { Config } from "tailwindcss"
const config: Config = {
// ... other config
theme: {
extend: {
colors: {
// Custom brand colors
primary: {
50: '#eff6ff',
100: '#dbeafe',
500: '#3b82f6', // Main brand color
600: '#2563eb',
900: '#1e3a8a',
},
// Custom accent colors
accent: {
500: '#10b981',
600: '#059669',
},
// Override default colors
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
},
fontFamily: {
// Custom fonts
sans: ['Inter', 'system-ui', 'sans-serif'],
heading: ['Poppins', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace'],
},
fontSize: {
// Custom font sizes
'xs': '0.75rem',
'sm': '0.875rem',
'base': '1rem',
'lg': '1.125rem',
'xl': '1.25rem',
'2xl': '1.5rem',
'3xl': '1.875rem',
'4xl': '2.25rem',
'5xl': '3rem',
}
},
},
}
Update your global CSS variables in app/globals.css
:
/* app/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
/* Light mode colors */
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 221.2 83.2% 53.3%;
--primary-foreground: 210 40% 98%;
/* Add your custom CSS variables */
--brand-primary: 221.2 83.2% 53.3%;
--brand-secondary: 210 40% 98%;
}
.dark {
/* Dark mode colors */
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--primary: 217.2 91.2% 59.8%;
--primary-foreground: 222.2 84% 4.9%;
}
}
Spacing & Sizing
Customize spacing, sizing, and layout utilities:
// tailwind.config.ts - extend spacing
theme: {
extend: {
spacing: {
'18': '4.5rem',
'88': '22rem',
'128': '32rem',
},
maxWidth: {
'8xl': '88rem',
'9xl': '96rem',
},
borderRadius: {
'xl': '1rem',
'2xl': '1.5rem',
'3xl': '2rem',
},
boxShadow: {
'soft': '0 2px 15px -3px rgba(0, 0, 0, 0.07), 0 10px 20px -2px rgba(0, 0, 0, 0.04)',
'strong': '0 10px 25px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
}
}
}
Custom Utilities
Add custom utility classes for common patterns:
/* app/globals.css */
@layer utilities {
/* Custom gradient backgrounds */
.bg-gradient-brand {
background: linear-gradient(135deg, theme('colors.primary.500'), theme('colors.primary.600'));
}
/* Custom text gradients */
.text-gradient {
background: linear-gradient(135deg, theme('colors.primary.500'), theme('colors.accent.500'));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* Custom animations */
.animate-fade-in {
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
}
Component Customization
Modello templates use a component-based architecture that makes customization straightforward and maintainable.
Modifying Existing Components
Most components are located in the components/
directory. Here's how to customize them:
// components/ui/button.tsx - Example button customization
import { cn } from "@/lib/utils"
import { ButtonHTMLAttributes, forwardRef } from "react"
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'default' | 'primary' | 'secondary' | 'outline' | 'ghost'
size?: 'sm' | 'md' | 'lg'
}
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant = 'default', size = 'md', ...props }, ref) => {
return (
<button
className={cn(
// Base styles
"inline-flex items-center justify-center rounded-md font-medium transition-colors",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
"disabled:pointer-events-none disabled:opacity-50",
// Variant styles
{
'bg-primary text-primary-foreground hover:bg-primary/90': variant === 'primary',
'bg-secondary text-secondary-foreground hover:bg-secondary/80': variant === 'secondary',
'border border-input hover:bg-accent hover:text-accent-foreground': variant === 'outline',
'hover:bg-accent hover:text-accent-foreground': variant === 'ghost',
},
// Size styles
{
'h-8 px-3 text-sm': size === 'sm',
'h-10 px-4': size === 'md',
'h-12 px-6 text-lg': size === 'lg',
},
className
)}
ref={ref}
{...props}
/>
)
}
)
export { Button }
Creating New Components
Follow these patterns when creating new components:
// components/custom/feature-card.tsx - Example new component
import { cn } from "@/lib/utils"
import { ReactNode } from "react"
interface FeatureCardProps {
title: string
description: string
icon?: ReactNode
className?: string
variant?: 'default' | 'highlighted'
}
export function FeatureCard({
title,
description,
icon,
className,
variant = 'default'
}: FeatureCardProps) {
return (
<div
className={cn(
"rounded-lg border p-6 transition-all hover:shadow-md",
{
'bg-card text-card-foreground': variant === 'default',
'bg-primary text-primary-foreground': variant === 'highlighted',
},
className
)}
>
{icon && (
<div className="mb-4 flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
{icon}
</div>
)}
<h3 className="mb-2 text-lg font-semibold">{title}</h3>
<p className="text-sm text-muted-foreground">{description}</p>
</div>
)
}
Component Patterns
Follow these patterns for consistent, maintainable components:
1. Use TypeScript interfaces for props
Define clear interfaces for component props to ensure type safety and better developer experience.
2. Implement variant patterns
Use variant props to create different visual styles while maintaining a single component.
3. Use the cn() utility for className merging
Always use the cn() utility from lib/utils.ts to properly merge Tailwind classes.
4. Forward refs when necessary
Use forwardRef for components that need to expose DOM element references.
Page Customization
Modello templates use Next.js App Router for page management. Here's how to customize, add, and remove pages.
Editing Existing Pages
Pages are located in the app/
directory. Each folder represents a route:
// app/about/page.tsx - Example page customization
import type { Metadata } from "next"
export const metadata: Metadata = {
title: "About Us | Your Company",
description: "Learn more about our company and mission",
}
export default function AboutPage() {
return (
<div className="container mx-auto px-4 py-16">
<div className="max-w-4xl mx-auto">
<h1 className="text-4xl font-bold mb-8">About Our Company</h1>
<div className="prose prose-lg max-w-none">
<p>
Your company story and mission statement goes here.
Customize this content to reflect your brand and values.
</p>
<h2>Our Mission</h2>
<p>
Describe your company's mission and what drives you to do what you do.
</p>
<h2>Our Team</h2>
<p>
Introduce your team members and their roles.
</p>
</div>
</div>
</div>
)
}
Adding New Pages
Create new pages by adding folders and page.tsx
files:
# Create a new page structure
mkdir app/services
touch app/services/page.tsx
# For nested routes
mkdir -p app/services/web-development
touch app/services/web-development/page.tsx
# This creates routes:
# /services
# /services/web-development
// app/services/page.tsx - New services page
import type { Metadata } from "next"
import { FeatureCard } from "@/components/custom/feature-card"
export const metadata: Metadata = {
title: "Our Services | Your Company",
description: "Explore our comprehensive range of services",
}
const services = [
{
title: "Web Development",
description: "Custom web applications built with modern technologies",
icon: "🌐"
},
{
title: "Mobile Apps",
description: "Native and cross-platform mobile applications",
icon: "📱"
},
// Add more services...
]
export default function ServicesPage() {
return (
<div className="container mx-auto px-4 py-16">
<div className="text-center mb-12">
<h1 className="text-4xl font-bold mb-4">Our Services</h1>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
We offer a comprehensive range of services to help your business succeed
</p>
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{services.map((service, index) => (
<FeatureCard
key={index}
title={service.title}
description={service.description}
icon={<span className="text-2xl">{service.icon}</span>}
/>
))}
</div>
</div>
)
}
Removing Pages
Remove pages by deleting their directories and updating navigation:
# Remove a page directory
rm -rf app/unwanted-page
# Update navigation components to remove links
# Edit components/header.tsx or similar navigation components
Update Navigation
Remember to update your navigation components and any internal links when removing pages to avoid broken links.
Layout Customization
Customize the overall layout structure by modifying layout files:
// app/layout.tsx - Root layout customization
import type { Metadata } from "next"
import { Inter } from 'next/font/google'
import { Header } from "@/components/header"
import { Footer } from "@/components/footer"
import "./globals.css"
const inter = Inter({ subsets: ["latin"] })
export const metadata: Metadata = {
title: {
default: "Your Company Name",
template: "%s | Your Company Name"
},
description: "Your company description",
keywords: ["keyword1", "keyword2", "keyword3"],
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" suppressHydrationWarning>
<body className={inter.className}>
<div className="min-h-screen flex flex-col">
<Header />
<main className="flex-1">
{children}
</main>
<Footer />
</div>
</body>
</html>
)
}
Assets & Media
Manage images, icons, and other static assets:
Images
- Place images in
public/images/
- Use Next.js Image component for optimization
- Provide alt text for accessibility
- Use appropriate formats (WebP, AVIF for modern browsers)
Icons
- Templates use Lucide React icons by default
- Replace favicon.ico in the public directory
- Update app/icon.tsx for dynamic icons
- Consider using SVG icons for scalability
// Example of using images in components
import Image from "next/image"
export function HeroSection() {
return (
<section className="relative">
<Image
src="/images/hero-background.jpg"
alt="Hero background"
width={1920}
height={1080}
className="object-cover"
priority // Load immediately for above-the-fold content
/>
<div className="absolute inset-0 bg-black/50">
<div className="container mx-auto px-4 py-16">
<h1 className="text-4xl font-bold text-white">
Your Hero Title
</h1>
</div>
</div>
</section>
)
}
Best Practices
Follow these best practices to maintain a high-quality, maintainable codebase:
Code Organization
- Keep components small and focused
- Use consistent naming conventions
- Group related components in folders
- Extract reusable logic into custom hooks
Performance
- Use Next.js Image component for images
- Implement lazy loading for heavy components
- Minimize bundle size with tree shaking
- Use dynamic imports for code splitting
Accessibility
- Use semantic HTML elements
- Provide alt text for images
- Ensure proper color contrast
- Test with keyboard navigation
SEO
- Use proper meta tags and titles
- Implement structured data
- Optimize page loading speeds
- Create XML sitemaps
Ready to Customize
With these customization techniques, you can transform your Modello template into a unique, branded experience that perfectly fits your needs.