Convert to template with dynamic configuration
Add comprehensive environment-based configuration system: - Created config.js module to centralize all environment variables - Updated server.js to use config module for all settings - Added /api/config endpoint to expose company info to frontend - Created init.js to dynamically inject config into HTML pages - Updated .env.example with comprehensive configuration options - Added data attributes to index.html for dynamic content - Updated Dockerfile to include config.js This allows users to customize: - Company name, tagline, and description - Branding colors (primary, accent, dark) - Contact information (email, phone, address, hours) - Social media links - About page content - Services offered 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5,11 +5,12 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Ryans Recruit Firm - Find Your Dream Job</title>
|
||||
<link rel="stylesheet" href="/css/styles.css">
|
||||
<script src="/js/init.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="container">
|
||||
<div class="logo">Ryans Recruit Firm</div>
|
||||
<div class="logo" data-company-name>Ryans Recruit Firm</div>
|
||||
<ul class="nav-links">
|
||||
<li><a href="/" class="active">Home</a></li>
|
||||
<li><a href="/about">About</a></li>
|
||||
@@ -23,8 +24,8 @@
|
||||
|
||||
<section class="hero">
|
||||
<div class="container">
|
||||
<h1>Your Career Success Is Our Mission</h1>
|
||||
<p>Connecting talented professionals with leading companies worldwide</p>
|
||||
<h1 data-company-tagline>Your Career Success Is Our Mission</h1>
|
||||
<p data-company-description>Connecting talented professionals with leading companies worldwide</p>
|
||||
<div style="display: flex; gap: 1rem; justify-content: center; margin-top: 2rem;">
|
||||
<a href="/jobs" class="btn btn-primary btn-lg">Browse Jobs</a>
|
||||
<a href="/contact" class="btn btn-secondary btn-lg">Get in Touch</a>
|
||||
@@ -35,7 +36,7 @@
|
||||
<section>
|
||||
<div class="container">
|
||||
<div class="section-title">
|
||||
<h2>Why Choose Ryans Recruit Firm?</h2>
|
||||
<h2>Why Choose <span data-company-name>Ryans Recruit Firm</span>?</h2>
|
||||
<p>We're committed to finding the perfect match for both candidates and employers</p>
|
||||
</div>
|
||||
|
||||
@@ -198,8 +199,8 @@
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<div class="footer-section">
|
||||
<h3>Ryans Recruit Firm</h3>
|
||||
<p style="color: rgba(255, 255, 255, 0.8);">
|
||||
<h3 data-company-name>Ryans Recruit Firm</h3>
|
||||
<p style="color: rgba(255, 255, 255, 0.8);" data-company-description>
|
||||
Your trusted partner in career advancement and talent acquisition.
|
||||
</p>
|
||||
</div>
|
||||
@@ -227,9 +228,9 @@
|
||||
<div class="footer-section">
|
||||
<h3>Contact</h3>
|
||||
<ul>
|
||||
<li>Email: info@ryansrecruit.com</li>
|
||||
<li>Phone: +1 (555) 123-4567</li>
|
||||
<li>Hours: Mon-Fri 9AM-6PM EST</li>
|
||||
<li>Email: <a href="mailto:info@ryansrecruit.com" data-contact-email>info@ryansrecruit.com</a></li>
|
||||
<li>Phone: <a href="tel:+15551234567" data-contact-phone>+1 (555) 123-4567</a></li>
|
||||
<li>Hours: <span data-business-hours>Mon-Fri 9AM-6PM EST</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
135
public/js/init.js
Normal file
135
public/js/init.js
Normal file
@@ -0,0 +1,135 @@
|
||||
// Initialize company configuration
|
||||
// This file loads company configuration from the API and updates the page
|
||||
|
||||
let siteConfig = {};
|
||||
|
||||
async function loadSiteConfig() {
|
||||
try {
|
||||
const response = await fetch('/api/config');
|
||||
siteConfig = await response.json();
|
||||
|
||||
// Update company information
|
||||
updateCompanyInfo();
|
||||
|
||||
// Update branding (colors)
|
||||
updateBranding();
|
||||
|
||||
// Update contact information
|
||||
updateContactInfo();
|
||||
|
||||
// Update social media links
|
||||
updateSocialLinks();
|
||||
|
||||
console.log('Site configuration loaded successfully');
|
||||
} catch (err) {
|
||||
console.error('Failed to load site configuration:', err);
|
||||
}
|
||||
}
|
||||
|
||||
function updateCompanyInfo() {
|
||||
// Update company name
|
||||
const companyNameElements = document.querySelectorAll('[data-company-name]');
|
||||
companyNameElements.forEach(el => {
|
||||
el.textContent = siteConfig.company.name;
|
||||
});
|
||||
|
||||
// Update company tagline
|
||||
const taglineElements = document.querySelectorAll('[data-company-tagline]');
|
||||
taglineElements.forEach(el => {
|
||||
el.textContent = siteConfig.company.tagline;
|
||||
});
|
||||
|
||||
// Update company description
|
||||
const descElements = document.querySelectorAll('[data-company-description]');
|
||||
descElements.forEach(el => {
|
||||
el.textContent = siteConfig.company.description;
|
||||
});
|
||||
|
||||
// Update page title
|
||||
const titleElement = document.querySelector('title');
|
||||
if (titleElement && titleElement.textContent.includes('Ryans Recruit')) {
|
||||
titleElement.textContent = titleElement.textContent.replace(/Ryans Recruit Firm|Ryans Recruit/g, siteConfig.company.name);
|
||||
}
|
||||
}
|
||||
|
||||
function updateBranding() {
|
||||
// Set CSS custom properties for branding colors
|
||||
const root = document.documentElement;
|
||||
root.style.setProperty('--primary-color', siteConfig.branding.primaryColor);
|
||||
root.style.setProperty('--accent-color', siteConfig.branding.accentColor);
|
||||
root.style.setProperty('--secondary-color', siteConfig.branding.darkColor);
|
||||
}
|
||||
|
||||
function updateContactInfo() {
|
||||
// Update email
|
||||
const emailElements = document.querySelectorAll('[data-contact-email]');
|
||||
emailElements.forEach(el => {
|
||||
if (el.tagName === 'A') {
|
||||
el.href = `mailto:${siteConfig.contact.email}`;
|
||||
}
|
||||
el.textContent = siteConfig.contact.email;
|
||||
});
|
||||
|
||||
// Update phone
|
||||
const phoneElements = document.querySelectorAll('[data-contact-phone]');
|
||||
phoneElements.forEach(el => {
|
||||
if (el.tagName === 'A') {
|
||||
el.href = `tel:${siteConfig.contact.phone}`;
|
||||
}
|
||||
el.textContent = siteConfig.contact.phone;
|
||||
});
|
||||
|
||||
// Update address
|
||||
const addressElements = document.querySelectorAll('[data-contact-address]');
|
||||
addressElements.forEach(el => {
|
||||
el.textContent = siteConfig.contact.address;
|
||||
});
|
||||
|
||||
// Update business hours
|
||||
const hoursElements = document.querySelectorAll('[data-business-hours]');
|
||||
hoursElements.forEach(el => {
|
||||
el.textContent = siteConfig.contact.businessHours;
|
||||
});
|
||||
}
|
||||
|
||||
function updateSocialLinks() {
|
||||
// Update LinkedIn
|
||||
const linkedinElements = document.querySelectorAll('[data-social-linkedin]');
|
||||
linkedinElements.forEach(el => {
|
||||
if (siteConfig.social.linkedin) {
|
||||
el.href = siteConfig.social.linkedin;
|
||||
el.style.display = '';
|
||||
} else {
|
||||
el.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// Update Twitter
|
||||
const twitterElements = document.querySelectorAll('[data-social-twitter]');
|
||||
twitterElements.forEach(el => {
|
||||
if (siteConfig.social.twitter) {
|
||||
el.href = siteConfig.social.twitter;
|
||||
el.style.display = '';
|
||||
} else {
|
||||
el.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// Update Facebook
|
||||
const facebookElements = document.querySelectorAll('[data-social-facebook]');
|
||||
facebookElements.forEach(el => {
|
||||
if (siteConfig.social.facebook) {
|
||||
el.href = siteConfig.social.facebook;
|
||||
el.style.display = '';
|
||||
} else {
|
||||
el.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Load configuration when DOM is ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', loadSiteConfig);
|
||||
} else {
|
||||
loadSiteConfig();
|
||||
}
|
||||
Reference in New Issue
Block a user