Initial Version
BIN
public/bestcity00.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
public/favicon.ico
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
9
public/home.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
|
||||
|
||||
<defs>
|
||||
</defs>
|
||||
<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)" >
|
||||
<polygon points="75.96,30.96 75.96,13.34 67.26,13.34 67.26,22.26 45,0 0.99,44.02 7.13,50.15 45,12.28 82.88,50.15 89.01,44.02 " style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) "/>
|
||||
<polygon points="45,20 14.04,50.95 14.04,90 35.29,90 35.29,63.14 54.71,63.14 54.71,90 75.96,90 75.96,50.95 " style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) "/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
17
public/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#006eff" />
|
||||
<link rel="icon" href="favicon.ico" />
|
||||
<link href='https://fonts.googleapis.com/css?family=Jost' rel='stylesheet'>
|
||||
<script>navigator.serviceWorker.register("/service-worker.js")</script>
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<title>RoyalCity</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
12
public/logo.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 72" width="128" height="72">
|
||||
<title>logo</title>
|
||||
<defs>
|
||||
<image width="256" height="256" id="img1" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIyNTYiIGhlaWdodD0iMjU2IiB2aWV3Qm94PSIwIDAgMjU2IDI1NiIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+Cgo8ZGVmcz4KPC9kZWZzPgo8ZyBzdHlsZT0ic3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDA7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2UtbWl0ZXJsaW1pdDogMTA7IGZpbGw6IG5vbmU7IGZpbGwtcnVsZTogbm9uemVybzsgb3BhY2l0eTogMTsiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuNDA2NTkzNDA2NTkzNDAxNiAxLjQwNjU5MzQwNjU5MzQwMTYpIHNjYWxlKDIuODEgMi44MSkiID4KCTxwb2x5Z29uIHBvaW50cz0iNzUuOTYsMzAuOTYgNzUuOTYsMTMuMzQgNjcuMjYsMTMuMzQgNjcuMjYsMjIuMjYgNDUsMCAwLjk5LDQ0LjAyIDcuMTMsNTAuMTUgNDUsMTIuMjggODIuODgsNTAuMTUgODkuMDEsNDQuMDIgIiBzdHlsZT0ic3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2UtbWl0ZXJsaW1pdDogMTA7IGZpbGw6IHJnYigwLDAsMCk7IGZpbGwtcnVsZTogbm9uemVybzsgb3BhY2l0eTogMTsiIHRyYW5zZm9ybT0iICBtYXRyaXgoMSAwIDAgMSAwIDApICIvPgoJPHBvbHlnb24gcG9pbnRzPSI0NSwyMCAxNC4wNCw1MC45NSAxNC4wNCw5MCAzNS4yOSw5MCAzNS4yOSw2My4xNCA1NC43MSw2My4xNCA1NC43MSw5MCA3NS45Niw5MCA3NS45Niw1MC45NSAiIHN0eWxlPSJzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1taXRlcmxpbWl0OiAxMDsgZmlsbDogcmdiKDAsMCwwKTsgZmlsbC1ydWxlOiBub256ZXJvOyBvcGFjaXR5OiAxOyIgdHJhbnNmb3JtPSIgIG1hdHJpeCgxIDAgMCAxIDAgMCkgIi8+CjwvZz4KPC9zdmc+"/>
|
||||
</defs>
|
||||
<style>
|
||||
.s0 { fill: #000000 }
|
||||
</style>
|
||||
<use id="home" href="#img1" transform="matrix(.213,0,0,.213,9.5,0)"/>
|
||||
<path id="FOR SALE" class="s0" aria-label="FOR
|
||||
SALE" d="m66.4 27v-17.5h10v2h-7.7v5.2h7v1.9h-7v8.4zm20.9-15.9q-2.5 0-4.1 1.9-1.5 2-1.5 5.3 0 3.3 1.5 5.2 1.6 1.9 4.1 1.9 2.6 0 4.1-1.9 1.5-1.9 1.5-5.2 0-3.3-1.5-5.3-1.5-1.9-4.1-1.9zm0-1.9q3.7 0 5.9 2.5 2.2 2.4 2.2 6.6 0 4.1-2.2 6.6-2.2 2.4-5.9 2.4-3.7 0-5.9-2.4-2.2-2.5-2.2-6.6 0-4.2 2.2-6.6 2.2-2.5 5.9-2.5zm20.1 9.6q0.8 0.3 1.5 1.1 0.7 0.8 1.4 2.3l2.4 4.8h-2.5l-2.2-4.5q-0.9-1.7-1.7-2.3-0.8-0.6-2.2-0.6h-2.6v7.4h-2.4v-17.5h5.4q3 0 4.4 1.3 1.5 1.2 1.5 3.7 0 1.7-0.8 2.8-0.7 1.1-2.2 1.5zm-2.9-7.4h-3v6.3h3q1.7 0 2.5-0.8 0.9-0.8 0.9-2.4 0-1.5-0.9-2.3-0.8-0.8-2.5-0.8zm-27.6 27.7v2.3q-1.3-0.7-2.5-1-1.2-0.3-2.3-0.3-2 0-3 0.8-1.1 0.7-1.1 2.1 0 1.2 0.7 1.8 0.7 0.5 2.7 0.9l1.4 0.3q2.6 0.5 3.9 1.8 1.3 1.2 1.3 3.4 0 2.5-1.7 3.8-1.7 1.3-5 1.3-1.3 0-2.7-0.2-1.4-0.3-2.9-0.9v-2.4q1.5 0.8 2.8 1.2 1.4 0.4 2.8 0.4 2 0 3.1-0.8 1.1-0.8 1.1-2.3 0-1.2-0.8-2-0.8-0.7-2.6-1.1l-1.4-0.2q-2.7-0.6-3.9-1.7-1.2-1.1-1.2-3.1 0-2.3 1.7-3.7 1.6-1.3 4.5-1.3 1.2 0 2.5 0.2 1.3 0.2 2.6 0.7zm14.3 10.4l-3.3-8.7-3.2 8.7zm-11.2 6.5l6.7-17.5h2.7l6.6 17.5h-2.4l-1.6-4.5h-7.9l-1.6 4.5zm18.6 0v-17.5h2.3v15.5h8.6v2zm13.3 0v-17.5h11.1v2h-8.7v5.2h8.3v2h-8.3v6.3h8.9v2z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/logo192.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/logo512.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
27
public/manifest.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "RoyalCity",
|
||||
"short_name": "RoyalCity",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"description": "RoyalCity is a modern real estate investment platform combining traditional property investing with cryptocurrency payments, featuring mobile-responsive design, smart contracts, and 3D property visualizations.",
|
||||
"lang": "english",
|
||||
"dir": "ltr",
|
||||
"theme_color": "#006eff",
|
||||
"background_color": "#ffffff",
|
||||
"orientation": "any",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/logo512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "/logo192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
}
|
||||
],
|
||||
"prefer_related_applications": false
|
||||
}
|
||||
BIN
public/models/house1.glb
Normal file
BIN
public/royalcity00.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
93
public/service-worker.js
Normal file
@@ -0,0 +1,93 @@
|
||||
|
||||
// Based off of https://github.com/pwa-builder/PWABuilder/blob/main/docs/sw.js
|
||||
|
||||
/*
|
||||
Welcome to our basic Service Worker! This Service Worker offers a basic offline experience
|
||||
while also being easily customizeable. You can add in your own code to implement the capabilities
|
||||
listed below, or change anything else you would like.
|
||||
|
||||
|
||||
Need an introduction to Service Workers? Check our docs here: https://docs.pwabuilder.com/#/home/sw-intro
|
||||
Want to learn more about how our Service Worker generation works? Check our docs here: https://docs.pwabuilder.com/#/studio/existing-app?id=add-a-service-worker
|
||||
|
||||
Did you know that Service Workers offer many more capabilities than just offline?
|
||||
- Background Sync: https://microsoft.github.io/win-student-devs/#/30DaysOfPWA/advanced-capabilities/06
|
||||
- Periodic Background Sync: https://web.dev/periodic-background-sync/
|
||||
- Push Notifications: https://microsoft.github.io/win-student-devs/#/30DaysOfPWA/advanced-capabilities/07?id=push-notifications-on-the-web
|
||||
- Badges: https://microsoft.github.io/win-student-devs/#/30DaysOfPWA/advanced-capabilities/07?id=application-badges
|
||||
*/
|
||||
|
||||
const HOSTNAME_WHITELIST = [
|
||||
self.location.hostname,
|
||||
'fonts.gstatic.com',
|
||||
'fonts.googleapis.com',
|
||||
'cdn.jsdelivr.net'
|
||||
]
|
||||
|
||||
// The Util Function to hack URLs of intercepted requests
|
||||
const getFixedUrl = (req) => {
|
||||
var now = Date.now()
|
||||
var url = new URL(req.url)
|
||||
|
||||
// 1. fixed http URL
|
||||
// Just keep syncing with location.protocol
|
||||
// fetch(httpURL) belongs to active mixed content.
|
||||
// And fetch(httpRequest) is not supported yet.
|
||||
url.protocol = self.location.protocol
|
||||
|
||||
// 2. add query for caching-busting.
|
||||
// Github Pages served with Cache-Control: max-age=600
|
||||
// max-age on mutable content is error-prone, with SW life of bugs can even extend.
|
||||
// Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
|
||||
// Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
|
||||
if (url.hostname === self.location.hostname) {
|
||||
url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
|
||||
}
|
||||
return url.href
|
||||
}
|
||||
|
||||
/**
|
||||
* @Lifecycle Activate
|
||||
* New one activated when old isnt being used.
|
||||
*
|
||||
* waitUntil(): activating ====> activated
|
||||
*/
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(self.clients.claim())
|
||||
})
|
||||
|
||||
/**
|
||||
* @Functional Fetch
|
||||
* All network requests are being intercepted here.
|
||||
*
|
||||
* void respondWith(Promise<Response> r)
|
||||
*/
|
||||
self.addEventListener('fetch', event => {
|
||||
// Skip some of cross-origin requests, like those for Google Analytics.
|
||||
if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
|
||||
// Stale-while-revalidate
|
||||
// similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
|
||||
// Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
|
||||
const cached = caches.match(event.request)
|
||||
const fixedUrl = getFixedUrl(event.request)
|
||||
const fetched = fetch(fixedUrl, { cache: 'no-store' })
|
||||
const fetchedCopy = fetched.then(resp => resp.clone())
|
||||
|
||||
// Call respondWith() with whatever we get first.
|
||||
// If the fetch fails (e.g disconnected), wait for the cache.
|
||||
// If there’s nothing in cache, wait for the fetch.
|
||||
// If neither yields a response, return offline pages.
|
||||
event.respondWith(
|
||||
Promise.race([fetched.catch(_ => cached), cached])
|
||||
.then(resp => resp || fetched)
|
||||
.catch(_ => { /* eat any errors */ })
|
||||
)
|
||||
|
||||
// Update the cache with the version we fetched (only for ok status)
|
||||
event.waitUntil(
|
||||
Promise.all([fetchedCopy, caches.open("pwa-cache")])
|
||||
.then(([response, cache]) => response.ok && cache.put(event.request, response))
|
||||
.catch(_ => { /* eat any errors */ })
|
||||
)
|
||||
}
|
||||
})
|
||||