6 Commits

Author SHA1 Message Date
7f2448f04a Update src/app/layout.tsx 2026-03-07 09:41:54 +00:00
464d5a532b Update src/app/page.tsx 2026-03-07 09:40:14 +00:00
81460f0cb7 Update src/app/layout.tsx 2026-03-07 09:40:13 +00:00
cab98834de Add public/sw.js 2026-03-07 09:40:12 +00:00
5746922358 Add public/manifest.json 2026-03-07 09:40:12 +00:00
fe6dd44a62 Merge version_1 into main
Merge version_1 into main
2026-03-07 09:38:17 +00:00
4 changed files with 176 additions and 10 deletions

10
public/manifest.json Normal file
View File

@@ -0,0 +1,10 @@
{
"name": "Rosslyn Inn & Suites", "short_name": "Rosslyn Inn", "description": "Experience timeless comfort and hospitality at Rosslyn Inn and Suites", "start_url": "/", "display": "standalone", "background_color": "#ffffff", "theme_color": "#000000", "orientation": "portrait-primary", "icons": [
{
"src": "/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any"
},
{
"src": "/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any"
}
]
}

96
public/sw.js Normal file
View File

@@ -0,0 +1,96 @@
const CACHE_NAME = 'rosslyn-inn-v1';
const urlsToCache = [
'/',
'/index.html',
'/manifest.json'
];
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
.catch((error) => {
console.error('Cache opening failed:', error);
})
);
});
self.addEventListener('fetch', (event) => {
const { request } = event;
const url = new URL(request.url);
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
return;
}
if (request.method !== 'GET') {
return;
}
event.respondWith(
caches.match(request)
.then((response) => {
if (response) {
return response;
}
return fetch(request)
.then((response) => {
if (!response || response.status !== 200 || response.type === 'error') {
return response;
}
const responseToCache = response.clone();
const isImage = request.headers.get('accept')?.includes('image');
const isFont = request.headers.get('accept')?.includes('font') || request.url.includes('.woff') || request.url.includes('.woff2');
const isScript = request.headers.get('accept')?.includes('javascript');
const isStylesheet = request.headers.get('accept')?.includes('text/css');
if (isImage || isFont || isScript || isStylesheet) {
caches.open(CACHE_NAME)
.then((cache) => {
cache.put(request, responseToCache);
})
.catch((error) => {
console.error('Cache update failed:', error);
});
}
return response;
})
.catch(() => {
if (request.destination === 'image') {
return new Response(
'<svg role="img" aria-label="Placeholder" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect fill="#ddd" width="100" height="100"/></svg>',
{ headers: { 'Content-Type': 'image/svg+xml', 'Cache-Control': 'no-store' } }
);
}
return new Response('Network request failed and no cache available', {
status: 503,
statusText: 'Service Unavailable',
headers: new Headers({
'Content-Type': 'text/plain'
})
});
});
})
);
});
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (cacheName !== CACHE_NAME) {
console.log('Deleting old cache:', cacheName);
return caches.delete(cacheName);
}
})
);
})
);
});

View File

@@ -16,28 +16,27 @@ const inter = Inter({
});
const sourceSans3 = Source_Sans_3({
variable: "--font-source-sans-3", subsets: ["latin"]
variable: "--font-source-sans-3", subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Rosslyn Inn & Suites | Luxury Hotel Accommodations", description: "Experience timeless comfort at Rosslyn Inn and Suites. Luxury rooms, world-class amenities, and personalized hospitality. Book your perfect stay today.", keywords: "hotel, accommodation, luxury rooms, hospitality, booking, suites", metadataBase: new URL("https://www.rosslyninn.com"),
alternates: {
canonical: "https://www.rosslyninn.com"
},
canonical: "https://www.rosslyninn.com"},
openGraph: {
title: "Rosslyn Inn & Suites | Premium Hotel Experience", description: "Discover luxury accommodations, fine dining, spa services, and exceptional hospitality.", url: "https://www.rosslyninn.com", siteName: "Rosslyn Inn & Suites", type: "website", images: [
{
url: "http://img.b2bpic.net/free-photo/business-professional-finding-new-ideas-forge-international-partnership-before-attending-conference-hotel-lounge-area-ceo-taking-notes-preparing-important-speech_482257-68049.jpg", alt: "Elegant hotel lobby at Rosslyn Inn and Suites"
}
]
url: "http://img.b2bpic.net/free-photo/business-professional-finding-new-ideas-forge-international-partnership-before-attending-conference-hotel-lounge-area-ceo-taking-notes-preparing-important-speech_482257-68049.jpg", alt: "Elegant hotel lobby at Rosslyn Inn and Suites"},
],
},
twitter: {
card: "summary_large_image", title: "Rosslyn Inn & Suites | Luxury Hotel", description: "Book your luxury stay with premium rooms, amenities, and hospitality.", images: ["http://img.b2bpic.net/free-photo/business-professional-finding-new-ideas-forge-international-partnership-before-attending-conference-hotel-lounge-area-ceo-taking-notes-preparing-important-speech_482257-68049.jpg"]
card: "summary_large_image", title: "Rosslyn Inn & Suites | Luxury Hotel", description: "Book your luxury stay with premium rooms, amenities, and hospitality.", images: [
"http://img.b2bpic.net/free-photo/business-professional-finding-new-ideas-forge-international-partnership-before-attending-conference-hotel-lounge-area-ceo-taking-notes-preparing-important-speech_482257-68049.jpg"],
},
robots: {
index: true,
follow: true
}
follow: true,
},
};
export default function RootLayout({
@@ -47,6 +46,67 @@ export default function RootLayout({
}>) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<script
async
src="https://cdn.jsdelivr.net/npm/workbox-window@7/build/workbox-window.umd.js"
></script>
<script>
{`
if ('serviceWorker' in navigator) {
window.addEventListener('load', async () => {
try {
const registration = await navigator.serviceWorker.register('/sw.js');
console.log('Service Worker registered:', registration);
} catch (error) {
console.error('Service Worker registration failed:', error);
}
});
}
`}
</script>
<script>
{`
if (typeof window !== 'undefined' && 'performance' in window) {
window.addEventListener('load', () => {
const perfData = window.performance.timing;
const pageLoadTime = perfData.loadEventEnd - perfData.navigationStart;
const resourcesPerf = window.performance.getEntriesByType('resource');
const metrics = {
pageLoadTime: pageLoadTime,
domInteractive: perfData.domInteractive - perfData.navigationStart,
domComplete: perfData.domComplete - perfData.navigationStart,
resourceCount: resourcesPerf.length,
timestamp: new Date().toISOString()
};
if ('sendBeacon' in navigator) {
navigator.sendBeacon('/api/metrics', JSON.stringify(metrics));
}
console.log('Performance Metrics:', metrics);
});
if ('PerformanceObserver' in window) {
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('Web Vital:', {
name: entry.name,
value: entry.value,
rating: entry.rating
});
}
});
observer.observe({
entryTypes: ['largest-contentful-paint', 'first-input', 'layout-shift']
});
}
}
`}
</script>
</head>
<ServiceWrapper>
<body
className={`${halant.variable} ${inter.variable} ${sourceSans3.variable} antialiased`}

View File

@@ -206,4 +206,4 @@ export default function LandingPage() {
</div>
</ThemeProvider>
);
}
}