From fae7589674d7dd50dca656ed2bd048af0e0e3366 Mon Sep 17 00:00:00 2001 From: Deep Govani Date: Fri, 26 Sep 2025 15:24:44 +0530 Subject: [PATCH 1/6] rem: firebase-messaging --- firebase.json | 9 -------- rollup.config.ts | 16 -------------- src/firebase-messaging-sw.ts | 42 ------------------------------------ 3 files changed, 67 deletions(-) delete mode 100644 src/firebase-messaging-sw.ts diff --git a/firebase.json b/firebase.json index cc63270c..6235787e 100644 --- a/firebase.json +++ b/firebase.json @@ -44,15 +44,6 @@ "value": "same-origin" } ] - }, - { - "source": "/@(service-worker|firebase-messaging-sw).js", - "headers": [ - { - "key": "Cache-Control", - "value": "no-cache, no-store, must-revalidate" - } - ] } ] }, diff --git a/rollup.config.ts b/rollup.config.ts index 86d335a3..6ba4d656 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -13,22 +13,6 @@ import { compileBufferTemplate, production } from './utils/build'; const { ROLLUP_WATCH } = process.env; export default [ - { - input: 'src/firebase-messaging-sw.ts', - treeshake: production, - output: { - file: 'dist/firebase-messaging-sw.js', - sourcemap: production, - }, - plugins: [ - nodeResolve(), - typescript({ - noEmitOnError: true, - sourceMap: production, - }), - production && terser(), - ], - }, { treeshake: production, output: { diff --git a/src/firebase-messaging-sw.ts b/src/firebase-messaging-sw.ts deleted file mode 100644 index 8759ca55..00000000 --- a/src/firebase-messaging-sw.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint spaced-comment: ["error", "always", { "markers": ["/"] }] */ -/* eslint-env serviceworker */ - -/// -/// -/// - -// Default type of `self` is `WorkerGlobalScope & typeof globalThis` -// https://github.com/microsoft/TypeScript/issues/14877 -declare const self: ServiceWorkerGlobalScope; - -// TODO: Migrate to v9 with imports -importScripts('/__/firebase/8.10.0/firebase-app.js'); -importScripts('/__/firebase/8.10.0/firebase-messaging.js'); -// This is currently the only method of loading -importScripts('/__/firebase/init.js'); - -import { MessagePayload, onBackgroundMessage } from 'firebase/messaging/sw'; -import { TempAny } from './temp-any'; - -const messaging = (self as any).firebase.messaging(); - -const showNotification = (payload: MessagePayload) => { - const data = payload.data as TempAny; - const body = data.body; - const icon = data.icon; - const title = data.title; - const notificationOptions = { body, icon, data }; - - return self.registration.showNotification(title, notificationOptions); -}; - -// This seems to get called when site is closed -messaging.setBackgroundMessageHandler(showNotification); - -// This seems to get called when site is open -onBackgroundMessage(messaging, showNotification); - -self.addEventListener('notificationclick', (event) => { - event.notification.close(); - event.waitUntil(self.clients.openWindow(event.notification.data.path)); -}); From 409a4e6cc1b96c64485fee091f71964a1d588fd7 Mon Sep 17 00:00:00 2001 From: Deep Govani Date: Fri, 26 Sep 2025 18:18:56 +0530 Subject: [PATCH 2/6] fix: prerender functionto load page on refresh --- functions/src/prerender.ts | 53 ++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/functions/src/prerender.ts b/functions/src/prerender.ts index 0c6ac700..dcb863e6 100644 --- a/functions/src/prerender.ts +++ b/functions/src/prerender.ts @@ -4,7 +4,7 @@ import express from 'express'; import { getFirestore } from 'firebase-admin/firestore'; import * as functions from 'firebase-functions'; import fetch from 'node-fetch'; -import url, { URL } from 'url'; +import url from 'url'; const app = express(); @@ -55,38 +55,35 @@ const checkForBots = (userAgent) => { // // The trick is on L66, pwaShell(): You must update that file! Open for explainer. app.get('*', async (req, res) => { - // What say you bot tester? const botResult = checkForBots(req.headers['user-agent']); + if (botResult) { - // Get me the url all nice - const targetUrl = generateUrl(req); + // Bot path via Rendertron (you can keep your caching here if you want) + const targetUrl = await generateUrl(req); + const rendertron = await getRendertronServer(); - // Did you read the README? You should have set rendertron document - // to where ever you deployed https://github.com/GoogleChrome/rendertron on AppEngine - fetch(`${await getRendertronServer()}/render/${targetUrl}`) - .then((res) => res.text()) - .then((body) => { - // We set Vary because we only want to cache this result for the bots - // which we know based on the user-agent. Vary is very useful. - // Reading about Vary header: - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary - // https://www.fastly.com/blog/best-practices-using-vary-header/ - res.set('Cache-Control', 'public, max-age=300, s-maxage=600'); - res.set('Vary', 'User-Agent'); + const botResp = await fetch(`${rendertron}/render/${targetUrl}`); + const body = await botResp.text(); - res.send(body.toString()); - }); - } else { - // 1. Umm, Justin, why not just point to index.html? - // 2. Umm, Justin, why not just fetch() index.html from the domain? - // - // Valid things to ask internet peoples - // 1. function doesn't know about the public hosting as far as I can tell (docs don't offer opinion/example) - // 2. Could fetch and return...but I found copy+paste the index.html PWA shell into file returns faster - // const indexHTML = fs.readFileSync('./index.html').toString(); - const path = new URL('./index.html', import.meta.url).pathname; - res.sendFile(path); + res.set('Cache-Control', 'public, max-age=300, s-maxage=600'); + res.set('Vary', 'User-Agent'); + return res.send(body.toString()); } + + // ✅ Non-bot path: fetch the current Hosting HTML so it’s never stale + const site = await getSiteDomain(); + const htmlResp = await fetch(`https://${site}/index.html`, { + // prevent node-fetch from reusing cached responses + headers: { 'Cache-Control': 'no-cache' } + }); + const html = await htmlResp.text(); + + // No-cache for HTML so users revalidate on each load + res.set('Cache-Control', 'no-cache, no-store, must-revalidate'); + res.set('Pragma', 'no-cache'); + res.set('Expires', '0'); + + return res.status(htmlResp.status || 200).send(html); }); export const prerender = functions.https.onRequest(app); From a3ef8ab96ea6643b053c3180d07511e7d058ad04 Mon Sep 17 00:00:00 2001 From: Deep Govani Date: Fri, 26 Sep 2025 19:34:57 +0530 Subject: [PATCH 3/6] fix: get dynamic host in prerender function --- functions/src/prerender.ts | 60 ++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/functions/src/prerender.ts b/functions/src/prerender.ts index dcb863e6..12402420 100644 --- a/functions/src/prerender.ts +++ b/functions/src/prerender.ts @@ -4,34 +4,57 @@ import express from 'express'; import { getFirestore } from 'firebase-admin/firestore'; import * as functions from 'firebase-functions'; import fetch from 'node-fetch'; -import url from 'url'; +// import url from 'url'; const app = express(); -const getSiteDomain = async () => { - const doc = await getFirestore().collection('config').doc('site').get(); - return doc.data().domain; -}; +// const getSiteDomain = async () => { +// const doc = await getFirestore().collection('config').doc('site').get(); +// return doc.data().domain; +// }; const getRendertronServer = async () => { const doc = await getFirestore().collection('config').doc('rendertron').get(); return doc.data().server; }; +const normalizeHost = (h: string) => + h.replace(/^https?:\/\//, '').replace(/\/+$/, ''); + +const resolveHost = (req): string => { + // 1. Prefer Hosting/CDN header + const headerHost = + req.get('x-forwarded-host') || req.get('host') || req.hostname; + + if (headerHost) { + return normalizeHost(headerHost); + } + + // 2. Fallback to Firebase config + const cfgHost = functions.config()?.site?.domain as string | undefined; + if (cfgHost) { + return normalizeHost(cfgHost); + } + + // 3. Last fallback (safe default for dev) + return 'localhost:5000'; +}; + + /** * generateUrl() - Piece together request parts to form FQDN URL * @param {Object} request */ -const generateUrl = async (request) => { - // Why do we use config site.domain instead of the domain from - // the request? Because it'll give you the wrong domain (pointed at the - // cloudfunctions.net) - return url.format({ - protocol: request.protocol, - host: await getSiteDomain(), - pathname: request.originalUrl, - }); -}; +// const generateUrl = async (request) => { +// // Why do we use config site.domain instead of the domain from +// // the request? Because it'll give you the wrong domain (pointed at the +// // cloudfunctions.net) +// return url.format({ +// protocol: request.protocol, +// host: await getSiteDomain(), +// pathname: request.originalUrl, +// }); +// }; /** * checkForBots() - regex that UserAgent, find me a linkbot @@ -55,11 +78,12 @@ const checkForBots = (userAgent) => { // // The trick is on L66, pwaShell(): You must update that file! Open for explainer. app.get('*', async (req, res) => { + const host = resolveHost(req); const botResult = checkForBots(req.headers['user-agent']); if (botResult) { // Bot path via Rendertron (you can keep your caching here if you want) - const targetUrl = await generateUrl(req); + const targetUrl = `https://${host}${req.originalUrl}`; const rendertron = await getRendertronServer(); const botResp = await fetch(`${rendertron}/render/${targetUrl}`); @@ -71,8 +95,8 @@ app.get('*', async (req, res) => { } // ✅ Non-bot path: fetch the current Hosting HTML so it’s never stale - const site = await getSiteDomain(); - const htmlResp = await fetch(`https://${site}/index.html`, { + // const site = await getSiteDomain(); + const htmlResp = await fetch(`https://${host}/index.html`, { // prevent node-fetch from reusing cached responses headers: { 'Cache-Control': 'no-cache' } }); From 2563faca3ed8b1be35322587917cce35f03ba36a Mon Sep 17 00:00:00 2001 From: Jaydip Umaretiya Date: Sun, 28 Sep 2025 09:48:32 +0530 Subject: [PATCH 4/6] Update meet-the-talent.json --- public/data/meet-the-talent.json | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/public/data/meet-the-talent.json b/public/data/meet-the-talent.json index 2e9f261e..0aae31ba 100644 --- a/public/data/meet-the-talent.json +++ b/public/data/meet-the-talent.json @@ -38,6 +38,44 @@ "name": "X/Twitter" } ] + },{ + "fullName": "Jaydip Umaretiya", + "location": "Surat, Gujarat, India", + "bio": "Experienced Android developer with 10+ years of expertise in building native mobile and TV applications, including digital signage solutions. Proficient in Kotlin, Java, Jetpack Compose, and native libraries, with strong skills in creating modern, responsive UIs. Well-versed in Kotlin Multiplatform (KMP) and Compose Multiplatform (CMP) to deliver scalable cross-platform solutions. Adept at project leadership, team mentoring, and managing complex, high-impact applications. Committed to innovation, exceeding client expectations, and fostering long-term partnerships.", + "email": "jaynumaretiya@gmail.com", + "phone": "+91-9510086772", + "imageUrl": "https://www.jaydip.tech/static/media/img-mobile.ec99727dfdae5c2cdd64.png", + "website": "https://jaydip.tech/", + "skills": [ + "Android", + "Kotlin", + "Jetpack Compose", + "Android TV Development", + "Kotlin MultiPlatform", + "Compose MultiPlatform" + ], + "links": [ + { + "icon": "website", + "link": "https://jaydip.tech/", + "name": "Portfolio" + }, + { + "icon": "github", + "link": "https://github.com/jaydipumaretiya", + "name": "Github" + }, + { + "icon": "linkedin", + "link": "https://www.linkedin.com/in/jaydipumaretiya", + "name": "LinkedIn" + }, + { + "icon": "twitter", + "link": "https://x.com/jaydipumaretiya", + "name": "X/Twitter" + } + ] } ] } \ No newline at end of file From 33a680d660a8c2bbcbc27715d5e8bfb21aa1c778 Mon Sep 17 00:00:00 2001 From: Deep Govani Date: Mon, 29 Sep 2025 18:05:07 +0530 Subject: [PATCH 5/6] fix: blank page shown when opening URL directly --- functions/src/prerender.ts | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/functions/src/prerender.ts b/functions/src/prerender.ts index 12402420..6b6c7eac 100644 --- a/functions/src/prerender.ts +++ b/functions/src/prerender.ts @@ -4,15 +4,9 @@ import express from 'express'; import { getFirestore } from 'firebase-admin/firestore'; import * as functions from 'firebase-functions'; import fetch from 'node-fetch'; -// import url from 'url'; const app = express(); -// const getSiteDomain = async () => { -// const doc = await getFirestore().collection('config').doc('site').get(); -// return doc.data().domain; -// }; - const getRendertronServer = async () => { const doc = await getFirestore().collection('config').doc('rendertron').get(); return doc.data().server; @@ -40,22 +34,6 @@ const resolveHost = (req): string => { return 'localhost:5000'; }; - -/** - * generateUrl() - Piece together request parts to form FQDN URL - * @param {Object} request - */ -// const generateUrl = async (request) => { -// // Why do we use config site.domain instead of the domain from -// // the request? Because it'll give you the wrong domain (pointed at the -// // cloudfunctions.net) -// return url.format({ -// protocol: request.protocol, -// host: await getSiteDomain(), -// pathname: request.originalUrl, -// }); -// }; - /** * checkForBots() - regex that UserAgent, find me a linkbot * @param {String} userAgent @@ -95,7 +73,6 @@ app.get('*', async (req, res) => { } // ✅ Non-bot path: fetch the current Hosting HTML so it’s never stale - // const site = await getSiteDomain(); const htmlResp = await fetch(`https://${host}/index.html`, { // prevent node-fetch from reusing cached responses headers: { 'Cache-Control': 'no-cache' } From d064767dbbb1266a2214708b15058c77a599da0f Mon Sep 17 00:00:00 2001 From: Deep Govani Date: Tue, 30 Sep 2025 13:04:22 +0530 Subject: [PATCH 6/6] add: coupon code information --- src/pages/registration-page.ts | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/pages/registration-page.ts b/src/pages/registration-page.ts index 50d3cb9f..4269106d 100644 --- a/src/pages/registration-page.ts +++ b/src/pages/registration-page.ts @@ -240,6 +240,39 @@ export class RegistrationPage extends PolymerElement { font-weight: 700; padding-bottom: 8px; } + + .ticket-coupon-info { + margin: 32px 0; + padding: 24px; + background-color: #fef7f7; + border-left: 6px solid #e53935; + border-radius: 10px; + font-size: 16px; + line-height: 1.6; + color: #333; + } + + .ticket-coupon-info strong { + font-weight: bold; + } + + .ticket-coupon-info ul { + list-style: none; + padding-left: 8px; + margin: 12px 0; + } + + .ticket-coupon-info ul li::before { + content: ''; + margin-right: 8px; + } + + @media (max-width: 768px) { + .ticket-coupon-info { + font-size: 15px; + padding: 20px; + } + } @@ -408,6 +441,19 @@ export class RegistrationPage extends PolymerElement {

This helps us avoid overcrowding and ensures that everyone gets the most out of the sessions they’re truly passionate about.

+
+

🚫 Coupon code? Seriously?!

+

🎟️ અમારી ટિકિટની કિંમત પહેલાંથી જ community ને ધ્યાનમાં રાખીને રાખવામાં આવી છે — it's already a highly subsidized price considering the amazing value you get!

+
    +
  • 🍱 Delicious food.
  • +
  • 👕 Swags you’ll love.
  • +
  • 🧠 Expert talks.
  • +
  • 💡 Immense learning.
  • +
  • 🎉 And a full-day networking with like-minded tech folks.
  • +
+

💬 Coupon code માંગીને શરમાવશો નહીં — એક દિવસ પિઝ્ઝા પાર્ટી ના ખર્ચે, તમારું ભવિષ્ય સુધારવાની તક છે.

+

👉 Knowledge મા investment કરશો, regret નહીં થાય.

+

Ticket Types