Rooftop Energy Digital Namecard
A mobile-first, dark-mode single-page application that presents Rooftop Energy staff namecards with clear CTAs, vCard download, and contact details copying functionality.
🚀 Features
- Contact CTAs: Call, Email, WhatsApp, and LinkedIn buttons
- vCard Download: Generate and download contact information as .vcf files
- Copy Details: Copy all contact information to clipboard
- URL Overrides: Customize details via query parameters for quick sharing
- Responsive Design: Optimized for mobile with graceful desktop scaling
- Dark Mode: Professional dark theme with Rooftop Energy branding
🛠️ Tech Stack
- Framework: Next.js 14 (App Router)
- Styling: Tailwind CSS
- Icons: Lucide React
- Fonts: Exo 2 (Google Fonts)
- Deployment: VPS-ready with static export and reverse proxy support
📁 Project Structure
src/
├── app/
│ ├── globals.css # Global styles and Tailwind imports
│ ├── layout.tsx # Root layout with font loading
│ ├── page.tsx # Main page with employee directory
│ ├── [employeeId]/ # Dynamic routes for individual employees
│ │ └── page.tsx # Individual employee namecard page
│ └── not-found.tsx # Custom 404 page
├── components/
│ └── Namecard.tsx # Main namecard component
└── config/
├── staff.ts # Base staff profile interface
└── employees.ts # All employee data and utilities
public/
├── logo.png # Company logo (replace with actual file)
├── profilepic.png # Default profile picture
├── whatsapp.png # WhatsApp icon
└── linkedin.png # LinkedIn icon
⚙️ Configuration
Managing Employee Data
The application now supports multiple employees with individual routing. All employee data is stored in src/config/employees.ts.
Adding New Employees
To add a new employee, add an entry to the employees array:
{
id: "unique-employee-id", // URL-friendly identifier (e.g., "john-doe")
name: "John Doe", // Staff member's name
title: "Senior Energy Consultant", // Job title
phone: "+60 12-345 6789", // Formatted phone number
whatsapp: "60123456789", // WhatsApp number (digits only)
email: "john.doe@rooftop.my", // Email address
linkedin: "https://linkedin.com/in/johndoe", // LinkedIn profile URL
profilePic: "/profilepic.png" // Path to profile picture
}
Note: Company-wide settings (address, website, logo) are automatically applied from companySettings and don't need to be repeated for each employee.
URL Structure
Each employee gets their own URL:
- Homepage:
card.rooftop.my/- Shows all employees - Individual:
card.rooftop.my/john-doe- Shows John Doe's namecard - Direct sharing: Share individual employee URLs for targeted contact
URL Query Parameter Overrides
You can temporarily override any field via URL parameters:
https://yoursite.com/?name=Jane%20Smith&title=Energy%20Analyst&phone=%2B60123456789
Available parameters:
name- Staff nametitle- Job titlephone- Phone numberwa- WhatsApp numberemail- Email addresslinkedin- LinkedIn URLaddress- Address (use %0A for line breaks)site- Website URLlogo- Logo path
🎨 Branding
The application uses the Rooftop Energy brand colors:
- Primary Accent:
#fcd913(Rooftop yellow) - Background: Deep charcoal (
#0a0a0a) - Card Surface: Near-black (
#1a1a1a) - Borders: Muted indigo (
#2a2a3a) - Text: White and muted blue-gray (
#8b9bb4)
🚀 Getting Started
Prerequisites
- Node.js 18+
- npm or yarn
Installation
- Clone the repository:
git clone <your-repo-url>
cd rooftop-energy-namecard
- Install dependencies:
npm install
-
Replace the logo:
- Place your Rooftop Energy logo in
public/logo.png - Recommended: 120x120px transparent PNG or SVG
- Place your Rooftop Energy logo in
-
Update staff details in
src/config/staff.ts
Development
npm run dev
Open http://localhost:3000 to view the application.
Building
npm run build
The built application will be in the out/ directory.
🌐 Deployment
VPS + Reverse Proxy (Nginx example)
- Build static files:
npm run build
- Copy the
out/directory to your server, e.g./var/www/namecard:
scp -r out/ user@server:/var/www/namecard
- Configure Nginx:
server {
listen 80;
server_name example.com; # change to your domain
# Optional subpath base (set BASE_PATH to match, e.g. "/namecard")
# location /namecard/ {
# alias /var/www/namecard/;
# try_files $uri $uri/ /index.html;
# }
root /var/www/namecard;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
- If you want to serve from a subpath (e.g.
/namecard), set at build time:
BASE_PATH=/namecard NEXT_PUBLIC_BASE_URL=https://example.com/namecard npm run build
Then deploy the out/ directory to the path configured by Nginx.
- Reload Nginx:
sudo nginx -t && sudo systemctl reload nginx
📱 Mobile Optimization
- Touch targets are ≥44px height
- Optimized for 360-414px viewport widths
- Responsive grid layouts (2×2 on mobile, 1×4 on desktop)
- Mobile-first design approach
♿ Accessibility
- WCAG AA color contrast compliance
- Visible focus states
- Proper ARIA labels
- Semantic HTML structure
- Keyboard navigation support
🔧 Customization
Adding Multiple Profiles
To support multiple staff members, you can:
- Create a profiles directory:
src/config/profiles/ - Add individual profile files
- Modify the routing to support
/[username]paths - Update the main page to load profiles dynamically
Styling Changes
- Colors: Update
tailwind.config.js - Typography: Modify
src/app/globals.css - Layout: Edit
src/components/Namecard.tsx
📊 Performance
The application targets:
- Lighthouse Performance: ≥90
- Accessibility: ≥95
- Best Practices: ≥95
- SEO: ≥90
🤝 Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
📄 License
This project is proprietary to Rooftop Energy.
🆘 Support
For technical support or questions about the application, please contact the development team.
Note: Remember to replace public/logo.png with the actual Rooftop Energy logo before deploying!