Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Aug 14, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/integrations/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"label": "Integrate With",
"position": 4
}
73 changes: 73 additions & 0 deletions docs/integrations/lovable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Lovable

## YouTube Walkthrough

import YouTubePlayer from '@site/src/components/YouTubePlayer';

<YouTubePlayer videoId="4VENlb0OuAw" title="Lovable Integration" />

<br />

In this tutorial, we'll learn how to send SMS and email notifications from your Lovable.dev application. We'll use NotificationAPI for sending notifications and Supabase edge functions to ensure secure implementation.

## Why Use Edge Functions for Notifications?

When implementing notifications in your application, it's crucial to handle sensitive operations like sending SMS or emails securely. Frontend code is visible to everyone and can be modified by malicious users. This is why we need to use backend services like Supabase edge functions (or a service of your choice) to handle these operations.

## Step 1: Set Up NotificationAPI

The setup is straightforward and only takes a minute.

## Step 2: Modify and give this prompt to Lovable

**Sample Prompt:**

```javascript
// [WHEN X HAPPENS], send an SMS and Email notification [to recipient] using the following code from a Supabase edge function:

import notificationapi from 'notificationapi-node-server-sdk';

notificationapi.init('YOUR_CLIENT_ID', 'YOUR_CLIENT_SECRET');
await notificationapi.send({
type: 'alert', // type of notification
to: {
email: '[email protected]', // recipient's email
number: '+15005550006' // recipient's number
},
email: {
subject: 'New contact form submission received',
html: '<p>New contact form submission received.</p>'
},
sms: {
message: 'New contact form submission received.'
}
});
```

- Replace [WHEN X HAPPENS] with the event that triggers the notification
- Replace [to recipient] with who should receive the notification, possibly explaining how Lovable should retreive their email and phone number
- If you have a back-end different from Supabase, replace the "a Supabase edge function"
- Replace `YOUR_CLIENT_ID` and `YOUR_CLIENT_SECRET` with your NotificationAPI credentials

## Security Best Practices

When implementing notifications, follow these security guidelines:

1. **Control Message Recipients**

- Either limit who can receive messages (e.g., only to your team)
- Or control what the message says (use static templates)

2. **Never Trust User Input**

- If you include user-provided content in notification messages, bad actors can modify the message to send malicious content (spam, links to malicious sites, etc.)

3. **Implement Rate Limiting**
- Add limits to how many notifications a user can trigger
- Consider implementing user authentication for sensitive operations

Remember to always handle sensitive operations like sending notifications through backend services, never directly from the frontend.

## Feedback and support

If you have any questions or need help implementing notifications in your Lovable.dev application, feel free to reach out to us at [email protected]. We're here to help you create the best notification experience for your users.
118 changes: 118 additions & 0 deletions src/components/YouTubePlayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React, { useState } from 'react';

export default function YouTubePlayer({ videoId, title }) {
const [isPlaying, setIsPlaying] = useState(false);
const videoUrl = `https://www.youtube.com/embed/${videoId}`;

const handlePlay = () => {
setIsPlaying(true);
};

return (
<div
onClick={handlePlay}
style={{
position: 'relative',
width: '100%',
paddingTop: '56.25%', // 9/16 = 0.5625
background: '#000',
cursor: 'pointer'
}}
>
{!isPlaying && (
<div
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'rgba(0, 0, 0, 0.7)',
zIndex: 1
}}
>
<div
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '6rem',
lineHeight: '1',
fontWeight: 'bold',
color: '#fff',
textShadow:
'0 0 100px rgba(255, 255, 255, 0.8), 0 0 40px rgba(255, 255, 255, 0.4)',
textAlign: 'center',
padding: '1rem',
letterSpacing: '0.1em'
}}
>
{title}
</div>
<div
style={{
width: '72px',
height: '72px',
background:
'linear-gradient(0deg, rgba(255, 0, 0, 0.7) 0%, rgba(204, 0, 0, 0.7) 100%)',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transition: 'all 0.2s ease',
boxShadow:
'0 2px 4px rgba(0, 0, 0, 0.3), inset 0 1px 1px rgba(255, 255, 255, 0.2)',
zIndex: 2,
backdropFilter: 'blur(2px)'
}}
onMouseOver={(e) => {
e.currentTarget.style.transform = 'scale(1.1)';
e.currentTarget.style.boxShadow =
'0 4px 8px rgba(0, 0, 0, 0.4), inset 0 1px 1px rgba(255, 255, 255, 0.2)';
}}
onMouseOut={(e) => {
e.currentTarget.style.transform = 'scale(1)';
e.currentTarget.style.boxShadow =
'0 2px 4px rgba(0, 0, 0, 0.3), inset 0 1px 1px rgba(255, 255, 255, 0.2)';
}}
>
<div
style={{
width: 0,
height: 0,
borderStyle: 'solid',
borderWidth: '14px 0 14px 24px',
borderColor: 'transparent transparent transparent #ffffff',
marginLeft: '4px',
filter: 'drop-shadow(0 0 2px rgba(255, 255, 255, 0.5))'
}}
/>
</div>
</div>
)}
<iframe
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
display: isPlaying ? 'block' : 'none'
}}
src={isPlaying ? `${videoUrl}?autoplay=1` : videoUrl}
title="YouTube video player"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
/>
</div>
);
}