cal.com
cal.com copied to clipboard
feat: browser push notifications
What does this PR do?
This PR implements web push notifications for cal.com.
Fixes #14504 /claim #14504
https://www.loom.com/share/3e12532ba0be4214bdb827d319acb430?sid=d38fc961-14d0-4681-8d14-30b46faae927
Requirement/Documentation
- This would require documentation for self-hosting as this requires 2 new env variables.
- I have not yet created any document for this as I will need to discuss few things with a maintainer and then I can document all these changes.
Type of change
- New feature (non-breaking change which adds functionality)
How should this be tested?
- Create a new public-private key pair required for web push notifications using
npx web-push generate-vapid-keys
. - Add these keys in .env file
NEXT_PUBLIC_VAPID_PUBLIC_KEY
andVAPID_PRIVATE_KEY
. - Book meeting with event that requires confirmation. The notification will be received to the organizer.
- Caution: The web push notifications doesn't work in all the browsers. The chrome and firefox supports it fully as of now as per my research.
Edit (By Udit):-
- Execute ngrok http 3000 and use that url
- Go to /bookings page and click on 'Allow Notification'.
- then add
sendNotification'(packages/features/notifications/sendNotification.ts) anywhere like in handleNewBooking. use the
subscription` value from prisma studio NotificationsSubscription table.
You should see notification like this
Checklist
- I haven't added tests that prove my fix is effective or that my feature works
@thepradipvc is attempting to deploy a commit to the cal Team on Vercel.
A member of the Team first needs to authorize it.
💵 To receive payouts, sign up on Algora, link your Github account and connect with Stripe/Alipay.
Thank you for following the naming conventions! 🙏 Feel free to join our discord and post your PR link.
New and removed dependencies detected. Learn more about Socket for GitHub ↗︎
🚮 Removed packages: npm/@0no-co/[email protected], npm/@47ng/[email protected], npm/@47ng/[email protected], npm/@aashutoshrathi/[email protected], npm/@achrinza/[email protected], npm/@achrinza/[email protected], npm/@achrinza/[email protected], npm/@adobe/[email protected], npm/@algora/[email protected], npm/@alloc/[email protected], npm/@ampproject/[email protected], npm/@angular-devkit/[email protected], npm/@angular-devkit/[email protected], npm/@angular-devkit/[email protected], npm/@antfu/[email protected], npm/@anthropic-ai/[email protected], npm/@apidevtools/[email protected], npm/@apidevtools/[email protected], npm/@apidevtools/[email protected], npm/@apidevtools/[email protected], npm/@ardatan/[email protected], npm/@ardatan/[email protected], npm/@aw-web-design/[email protected], npm/@aws-crypto/[email protected], npm/@aws-crypto/[email protected], npm/@aws-crypto/[email protected], npm/@aws-crypto/[email protected], npm/@aws-crypto/[email protected], npm/@aws-crypto/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@aws-sdk/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@azure/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3, npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2, npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@babel/[email protected], npm/@base2/[email protected], npm/@bcoe/[email protected], npm/@boxyhq/[email protected], npm/@boxyhq/[email protected], npm/@boxyhq/[email protected], npm/@boxyhq/[email protected], npm/@braintree/[email protected], npm/@calcom/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@changesets/[email protected], npm/@chevrotain/[email protected], npm/@chevrotain/[email protected], npm/@chevrotain/[email protected], npm/@chevrotain/[email protected], npm/@colors/[email protected], npm/@cspotcode/[email protected], npm/@dabh/[email protected], npm/@daily-co/[email protected], npm/@daily-co/[email protected], npm/@date-io/[email protected], npm/@date-io/[email protected], npm/@datocms/[email protected], npm/@datocms/[email protected], npm/@datocms/[email protected], npm/@deploysentinel/[email protected], npm/@deploysentinel/[email protected], npm/@discoveryjs/[email protected], npm/@emotion/[email protected], npm/@emotion/[email protected], npm/@emotion/[email protected], npm/@emotion/[email protected], npm/@emotion/[email protected], npm/@emotion/[email protected], npm/@emotion/[email protected], npm/@emotion/[email protected], npm/@emotion/[email protected], npm/@emotion/[email protected], npm/@emotion/[email protected], npm/@emotion/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@esbuild/[email protected], npm/@eslint-community/[email protected], npm/@eslint-community/[email protected], npm/@eslint/[email protected], npm/@eslint/[email protected], npm/@ewsjs/[email protected], npm/@ewsjs/[email protected], npm/@faker-js/[email protected], npm/@fal-works/[email protected], npm/@fastify/[email protected], npm/@figspec/[email protected], npm/@figspec/[email protected], npm/@floating-ui/[email protected], npm/@floating-ui/[email protected], npm/@floating-ui/[email protected], npm/@floating-ui/[email protected], npm/@flodlc/[email protected], npm/@formatjs/[email protected], npm/@formatjs/[email protected], npm/@formatjs/[email protected], npm/@formatjs/[email protected], npm/@formatjs/[email protected], npm/@formatjs/[email protected], npm/@formatjs/[email protected], npm/@formatjs/[email protected], npm/@formbricks/[email protected], npm/@formbricks/[email protected], npm/@formkit/[email protected], npm/@gar/[email protected], npm/@getalby/[email protected], npm/@getalby/[email protected], npm/@glidejs/[email protected], npm/@golevelup/[email protected], npm/@googleapis/[email protected], npm/@graphql-codegen/[email protected], npm/@graphql-codegen/[email protected], npm/@graphql-codegen/[email protected], npm/@graphql-codegen/[email protected], npm/@graphql-codegen/[email protected], npm/@graphql-codegen/[email protected], npm/@graphql-codegen/[email protected], npm/@graphql-codegen/[email protected], npm/@graphql-codegen/[email protected], npm/@graphql-codegen/[email protected], npm/@graphql-codegen/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-tools/[email protected], npm/@graphql-typed-document-node/[email protected], npm/@grpc/[email protected], npm/@grpc/[email protected], npm/@hapi/[email protected], npm/@hapi/[email protected], npm/@headlessui/[email protected], npm/@heroicons/[email protected], npm/@hookform/[email protected], npm/@hookform/[email protected], npm/@hubspot/[email protected], npm/@humanwhocodes/[email protected], npm/@humanwhocodes/[email protected], npm/@humanwhocodes/[email protected], npm/@iarna/[email protected], npm/@ioredis/[email protected], npm/@isaacs/[email protected], npm/@istanbuljs/[email protected], npm/@istanbuljs/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jest/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jimp/[email protected], npm/@jridgewell/[email protected], npm/@jridgewell/[email protected], npm/@jridgewell/[email protected], npm/@js-joda/[email protected], npm/@jsdevtools/[email protected], npm/@juggle/[email protected], npm/@kamilkisiela/[email protected], npm/@langchain/[email protected], npm/@langchain/[email protected], npm/@langchain/[email protected], npm/@langchain/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lexical/[email protected], npm/@lit-labs/[email protected], npm/@lit/[email protected], npm/@ljharb/[email protected], npm/@lukeed/[email protected], npm/@manypkg/[email protected], npm/@manypkg/[email protected], npm/@mdx-js/[email protected], npm/@microsoft/[email protected], npm/@microsoft/[email protected], npm/@microsoft/[email protected], npm/@microsoft/[email protected], npm/@microsoft/[email protected], npm/@mongodb-js/[email protected], npm/@mrleebo/[email protected], npm/@mswjs/[email protected], npm/@mswjs/[email protected], npm/@mux/[email protected], npm/@mux/[email protected], npm/@mux/[email protected], npm/@mux/[email protected], npm/@ndelangen/[email protected], npm/@nestjs/[email protected], npm/@nestjs/[email protected], npm/@nestjs/[email protected], npm/@nestjs/[email protected], npm/@nestjs/[email protected], npm/@nestjs/[email protected], npm/@nestjs/[email protected], npm/@nestjs/[email protected], npm/@nestjs/[email protected], npm/@nestjs/[email protected], npm/@nestjs/[email protected], npm/@nestjs/[email protected], npm/@next-auth/[email protected], npm/@next/[email protected], npm/@next/[email protected], npm/@next/[email protected], npm/@next/[email protected], npm/@next/[email protected], npm/@next/[email protected], npm/@next/[email protected], npm/@next/[email protected], npm/@next/[email protected], npm/@next/[email protected], npm/@next/[email protected], npm/@next/[email protected], npm/@noble/[email protected], npm/@noble/[email protected], npm/@node-ipc/[email protected], npm/@nodelib/[email protected], npm/@nodelib/[email protected], npm/@prisma/[email protected], npm/@radix-ui/[email protected], npm/@sentry/[email protected], npm/@tanstack/[email protected], npm/@types/[email protected], npm/@types/[email protected], npm/@types/[email protected], npm/@types/[email protected], npm/@upstash/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected], npm/[email protected]
Hey @PeerRich , Can you please confirm the following considerations and answer a few questions about the implementation of the notifications I've done?
This PR is being marked as stale due to inactivity.
does it send all notifications we currently send by email?
No, I've just added the notifications for unconfirmed events for now. I wanted to make sure that what am doing is what's expected.
I had a few questions to discuss but if you prefer that I continue with what I find the best option then I can continue adding this to all other events. Can you also help me, is there any centralized place from where all emails are sent for events or do I have to find them myself?
Hey @Amit91848, I rebased my local branch to the latest changes on cal.com and found that there has been some refactoring. Also previously I only sent notifications for unconfirmed events. Can you tell me where exactly can I find code where we're sending emails so I can also send push notifications for that.
Graphite Automations
"Add consumer team as reviewer" took an action on this PR • (07/31/24)
1 reviewer was added to this PR based on Keith Williams's automation.
"Add foundation team as reviewer" took an action on this PR • (08/22/24)
1 reviewer was added to this PR based on Keith Williams's automation.
Hey @Amit91848 , Can you please guide me for what all things do we have to send notifications?
would love to get this merged and then built notifications for "Instant Meetings" upon this @Udit-takkar
tried to fix merge conflicts, havent tested but i think i did it right
Tooltip is going outside the page when notifications permission denied
Done
I am assuming calling sendNotification would be done in a separate PR
Yes
New and removed dependencies detected. Learn more about Socket for GitHub ↗︎
Package | New capabilities | Transitives | Size | Publisher |
---|---|---|---|---|
npm/[email protected] | network | 0 |
549 kB | panva |
🚮 Removed packages: npm/@formkit/[email protected]), npm/[email protected])