forward an email => get calendar event
That's it. No buttons, no clicking - just forward an email, and a calendar event gets added to your Google Calendar.
fwd2cal uses an LLM to parse the thread, generate a JSON of the event details, and then adds the event to your google calendar.
fwd2cal.com - running in production, free until it gets annoying/expensive to run.
fwd2cal.create.mp4
You can self host - it runs on firebase functions.
- Signup with an email: just email calendar@fwd2cal.com and you'll be sent a google auth link.
- Send from multiple email addresses: send
add myworkemail@address.comin the subject line to calendar@fwd2cal.com, and then you can add events to your google calendar from another email address - ICS attachment support: Forward emails with .ics calendar attachments to automatically add them to your calendar
- Multi-event extraction: Extract and add multiple events from a single email
- Email threading: Replies appear in the same email thread for better organization
- Completely private: No logging, or storage of any emails. All that is stored are your email addresses.
- That's it. The goal is to just do one thing correctly and stay out of the way of the user.
You will need:
- a firebase project
- an OpenRouter API key (for LLM access)
- a Cloudflare Email Service account for outbound transactional email
- a Resend account for inbound email and contact management
When you deploy or run the emulator firebase emulators:start, Firebase will prompt you to set the required parameters:
OPENROUTER_API_KEY- Your OpenRouter API keyCLOUDFLARE_ACCOUNT_ID- Your Cloudflare account IDCLOUDFLARE_EMAIL_API_TOKEN- A secret withEmail Sending: EditOUTBOUND_EMAIL_PROVIDER-cloudflare(default) orresendRESEND_API_KEY- Your Resend API key for inbound email and contactsRESEND_SIGNING_SECRET- Resend webhook signing secretPOSTHOG_API_KEY- (Optional) PostHog API key for analyticsENVIRONMENT_NAME- (Optional) Defaults to "production"
Configure Resend to forward incoming emails to your Firebase Functions webhook:
- In your Resend dashboard, set up email forwarding to:
https://{your project name}.web.app/v2/resendInboundCallback - be sure to copy the RESEND_SIGNING_SECRET after you set your callback url
- Make sure to configure your domain's DNS records in Resend to receive emails
Onboard each outbound sender domain in Cloudflare Email Service. The app sends
from calendar@fwd2cal.com and drive@fwd2drive.com, so both domains must show
Enabled and Configured under Email Sending.
Store the Cloudflare token in Firebase Secret Manager before deployment:
firebase functions:secrets:set CLOUDFLARE_EMAIL_API_TOKEN --project YOUR_PROJECT_IDCreate a functions/.env file with your local development credentials:
# Environment Configuration
ENVIRONMENT_NAME=local
# API Keys
OPENROUTER_API_KEY=sk-or-v1-YOUR_API_KEY
# Resend
RESEND_API_KEY=re_YOUR_API_KEY
RESEND_SIGNING_SECRET=whsec_YOUR_SECRET
# Cloudflare Email Service (store the API token with functions:secrets:set)
CLOUDFLARE_ACCOUNT_ID=YOUR_CLOUDFLARE_ACCOUNT_ID
# PostHog Analytics (optional)
POSTHOG_API_KEY=phc_YOUR_API_KEYAlso - you're probably going to want to save your credentials from https://console.cloud.google.com/apis/credentials to: functions/auth/v2-google-auth-credentials.json.
You want to make sure your redirect_uris are setup correctly. It is a list, [0] should be the default from firebase, [1] should be http://127.0.0.1:5002/v2/oauthCallback for local development, and [2] should be the prod url.
export TESTER_PRIMARY_GOOGLE_ACCT="your@gmail.com"
export TESTER_SECONDARY_EMAIL_ACCT="anotherEmailAddressThatYouUse@anything.com"
cd functions
npm testMake sure you authorize your google account in 30 seconds after starting the test so the tests can run.
The test suite mocks Cloudflare outbound sending and Resend inbound processing without making actual API calls.
To test scheduled functions (note: token refresh is currently disabled):
firebase functions:shell
v2refreshTokensScheduled()All contributions are welcome. I will do by best to keep main stable.
functions/util/prompts.js- Prompt engineers can help here. If you notice fwd2cal fail to add your event correctly, consider adding examples to the prompts to improve the AI's understanding.- Timezones - The current timezone detection could be improved for better accuracy across different formats and locations.
- Multiple calendars: Right now all events are added to the default calendar - the AI could potentially understand context and select an appropriate calendar.
- Find a way to add a test for the oAuth refresh tokens.
This was written by @moeadham to get familiar with firebase and structured data from LLMs - training for a much larger project I'm working on.