Add sequin guide (#1368)
Co-authored-by: James Ritchie <james@trigger.dev>
This commit is contained in:
@@ -10,11 +10,14 @@ import CardNodejs from "/snippets/card-nodejs.mdx";
|
||||
import CardNextjs from "/snippets/card-nextjs.mdx";
|
||||
import CardRemix from "/snippets/card-remix.mdx";
|
||||
import CardSupabase from "/snippets/card-supabase.mdx";
|
||||
import CardSequin from "/snippets/card-sequin.mdx";
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<CardBun />
|
||||
<CardNodejs />
|
||||
<CardNextjs />
|
||||
<CardRemix />
|
||||
<CardSequin />
|
||||
<CardSupabase />
|
||||
|
||||
</CardGroup>
|
||||
|
||||
@@ -0,0 +1,319 @@
|
||||
---
|
||||
title: "Sequin database triggers"
|
||||
sidebarTitle: "Sequin"
|
||||
description: "This guide will show you how to trigger tasks from database changes using Sequin"
|
||||
icon: "database"
|
||||
---
|
||||
|
||||
[Sequin](https://sequinstream.com) allows you to trigger tasks from database changes. Sequin captures every insert, update, and delete on a table and then ensures a task is triggered for each change.
|
||||
|
||||
Often, task runs coincide with database changes. For instance, you might want to use a Trigger.dev task to generate an embedding for each post in your database:
|
||||
|
||||
<Frame>
|
||||
<img src="/images/sequin-intro.svg" alt="Sequin and Trigger.dev Overview" />
|
||||
</Frame>
|
||||
|
||||
In this guide, you'll learn how to use Sequin to trigger Trigger.dev tasks from database changes.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You are about to create a [regular Trigger.dev task](/tasks-regular) that you will execute when ever a post is inserted or updated in your database. Sequin will detect all the changes on the `posts` table and then send the payload of the post to an API endpoint that will call `tasks.trigger()` to create the embedding and update the database.
|
||||
|
||||
As long as you create an HTTP endpoint that Sequin can deliver webhooks to, you can use any web framework or edge function (e.g. Supabase Edge Functions, Vercel Functions, Cloudflare Workers, etc.) to invoke your Trigger.dev task. In this guide, we'll show you how to setup Trigger.dev tasks using Next.js API Routes.
|
||||
|
||||
You'll need the following to follow this guide:
|
||||
|
||||
- A Next.js project with [Trigger.dev](https://trigger.dev) installed
|
||||
<Info>
|
||||
If you don't have one already, follow [Trigger.dev's Next.js setup guide](/guides/frameworks/nextjs) to setup your project. You can return to this guide when you're ready to write your first Trigger.dev task.
|
||||
</Info>
|
||||
- A [Sequin](https://console.sequinstream.com/register) account
|
||||
- A Postgres database (Sequin works with any Postgres database version 12 and up) with a `posts` table.
|
||||
|
||||
## Create a Trigger.dev task
|
||||
|
||||
Start by creating a new Trigger.dev task that takes in a Sequin change event as a payload, creates an embedding, and then inserts the embedding into the database:
|
||||
|
||||
<Steps titleSize="h3">
|
||||
<Step title="Create a `create-embedding-for-post` task">
|
||||
In your `src/trigger/tasks` directory, create a new file called `create-embedding-for-post.ts` and add the following code:
|
||||
|
||||
<CodeGroup>
|
||||
```ts trigger/create-embedding-for-post.ts
|
||||
import { task } from "@trigger.dev/sdk/v3";
|
||||
import { OpenAI } from "openai";
|
||||
import { upsertEmbedding } from "../util";
|
||||
|
||||
const openai = new OpenAI({
|
||||
apiKey: process.env.OPENAI_API_KEY,
|
||||
});
|
||||
|
||||
export const createEmbeddingForPost = task({
|
||||
id: "create-embedding-for-post",
|
||||
run: async (payload: {
|
||||
record: {
|
||||
id: number;
|
||||
title: string;
|
||||
body: string;
|
||||
author: string;
|
||||
createdAt: string;
|
||||
embedding: string | null;
|
||||
},
|
||||
metadata: {
|
||||
table_schema: string,
|
||||
table_name: string,
|
||||
consumer: {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
};
|
||||
}) => {
|
||||
// Create an embedding using the title and body of payload.record
|
||||
const content = `${payload.record.title}\n\n${payload.record.body}`;
|
||||
const embedding = (await openai.embeddings.create({
|
||||
model: "text-embedding-ada-002",
|
||||
input: content,
|
||||
})).data[0].embedding;
|
||||
|
||||
// Upsert the embedding in the database. See utils.ts for the implementation -> ->
|
||||
await upsertEmbedding(embedding, payload.record.id);
|
||||
|
||||
// Return the updated record
|
||||
return {
|
||||
...payload.record,
|
||||
embedding: JSON.stringify(embedding),
|
||||
};
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
```ts utils.ts
|
||||
import pg from "pg";
|
||||
|
||||
export async function upsertEmbedding(embedding: number[], id: number) {
|
||||
const client = new pg.Client({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
});
|
||||
await client.connect();
|
||||
|
||||
try {
|
||||
const query = `
|
||||
INSERT INTO post_embeddings (id, embedding)
|
||||
VALUES ($2, $1)
|
||||
ON CONFLICT (id)
|
||||
DO UPDATE SET embedding = $1
|
||||
`;
|
||||
const values = [JSON.stringify(embedding), id];
|
||||
|
||||
const result = await client.query(query, values);
|
||||
console.log(`Updated record in database. Rows affected: ${result.rowCount}`);
|
||||
|
||||
return result.rowCount;
|
||||
} catch (error) {
|
||||
console.error("Error updating record in database:", error);
|
||||
throw error;
|
||||
} finally {
|
||||
await client.end();
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
This task takes in a Sequin record event, creates an embedding, and then uppserts the embedding into a `post_embeddings` table.
|
||||
</Step>
|
||||
<Step title="Add the task to your Trigger.dev project">
|
||||
Register the `create-embedding-for-post` task to your Trigger.dev cloud project by running the following command:
|
||||
|
||||
```bash
|
||||
npx trigger.dev@latest dev
|
||||
```
|
||||
|
||||
In the Trigger.dev dashboard, you should now see the `create-embedding-for-post` task:
|
||||
|
||||
<Frame>
|
||||
<img src="/images/sequin-register-task.png" alt="Task added" />
|
||||
</Frame>
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Check>
|
||||
You've successfully created a Trigger.dev task that will create an embedding for each post in your database. In the next step, you'll create an API endpoint that Sequin can deliver records to.
|
||||
</Check>
|
||||
|
||||
## Setup API route
|
||||
|
||||
You'll now create an API endpoint that will receive posts from Sequin and then trigger the `create-embedding-for-post` task.
|
||||
|
||||
<Info>
|
||||
This guide covers how to setup an API endpoint using the Next.js App Router. You can find examples for Next.js Server Actions and Pages Router in the [Trigger.dev documentation](https://trigger.dev/docs/guides/frameworks/nextjs).
|
||||
</Info>
|
||||
|
||||
<Steps titleSize="h3">
|
||||
<Step title="Create a route handler">
|
||||
Add a route handler by creating a new `route.ts` file in a `/app/api/create-embedding-for-post` directory:
|
||||
|
||||
```ts app/api/create-embedding-for-post/route.ts
|
||||
import type { createEmbeddingForPost } from "@/trigger/create-embedding-for-post";
|
||||
import { tasks } from "@trigger.dev/sdk/v3";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const authHeader = req.headers.get('authorization');
|
||||
if (!authHeader || authHeader !== `Bearer ${process.env.SEQUIN_WEBHOOK_SECRET}`) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
const payload = await req.json();
|
||||
const handle = await tasks.trigger<typeof createEmbeddingForPost>(
|
||||
"create-embedding-for-post",
|
||||
payload
|
||||
);
|
||||
|
||||
return NextResponse.json(handle);
|
||||
}
|
||||
```
|
||||
|
||||
This route handler will receive records from Sequin, parse them, and then trigger the `create-embedding-for-post` task.
|
||||
</Step>
|
||||
<Step title="Set secret keys">
|
||||
You'll need to set four secret keys in a `.env.local` file:
|
||||
|
||||
```bash
|
||||
SEQUIN_WEBHOOK_SECRET=your-secret-key
|
||||
TRIGGER_SECRET_KEY=secret-from-trigger-dev
|
||||
OPENAI_API_KEY=sk-proj-asdfasdfasdf
|
||||
DATABASE_URL=postgresql://
|
||||
```
|
||||
|
||||
The `SEQUIN_WEBHOOK_SECRET` ensures that only Sequin can access your APIendpoint.
|
||||
|
||||
The `TRIGGER_SECRET_KEY` is used to authenticate requests to Trigger.dev and can be found in the **API keys** tab of the Trigger.dev dashboard.
|
||||
|
||||
The `OPENAI_API_KEY` and `DATABASE_URL` are used to create an embedding using OpenAI and connect to your database. Be sure to add these as [environment variables](https://trigger.dev/docs/deploy-environment-variables) in Trigger.dev as well.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Check>
|
||||
You've successfully created an API endpoint that can receive record payloads from Sequin and trigger a Trigger.dev task. In the next step, you'll setup Sequin to trigger the endpoint.
|
||||
</Check>
|
||||
|
||||
## Create Sequin consumer
|
||||
|
||||
You'll now configure Sequin to send every row in your `posts` table to your Trigger.dev task.
|
||||
|
||||
<Steps titleSize="h3">
|
||||
<Step title="Connect Sequin to your database">
|
||||
1. Login to your Sequin account and click the **Add New Database** button.
|
||||
2. Enter the connection details for your Postgres database.
|
||||
<Info>
|
||||
If you need to connect to a local dev database, flip the **use localhost** switch and follow the instructions to create a tunnel using the [Sequin CLI](/cli).
|
||||
</Info>
|
||||
3. Follow the instructions to create a publication and a replication slot by running two SQL commands in your database:
|
||||
|
||||
```sql
|
||||
create publication sequin_pub for all tables;
|
||||
select pg_create_logical_replication_slot('sequin_slot', 'pgoutput');
|
||||
```
|
||||
|
||||
4. Name your database and click the **Connect Database** button.
|
||||
|
||||
Sequin will connect to your database and ensure that it's configured properly.
|
||||
|
||||
<Note>
|
||||
If you need step-by-step connection instructions to connect Sequin to your database, check out our [quickstart guide](/quickstart).
|
||||
</Note>
|
||||
</Step>
|
||||
<Step title="Tunnel to your local endpoint">
|
||||
Now, create a tunnel to your local endpoint so Sequin can deliver change payloads to your local API:
|
||||
|
||||
1. In the Sequin console, open the **HTTP Endpoint** tab and click the **Create HTTP Endpoint** button.
|
||||
2. Enter a name for your endpoint (i.e. `local_endpoint`) and flip the **Use localhost** switch. Follow the instructions in the Sequin console to [install the Sequin CLI](/cli), then run:
|
||||
|
||||
```bash
|
||||
sequin tunnel --ports=3001:local_endpoint
|
||||
```
|
||||
|
||||
3. Now, click **Add encryption header** and set the key to `Authorization` and the value to `Bearer SEQUIN_WEBHOOK_SECRET`.
|
||||
4. Click **Create HTTP Endpoint**.
|
||||
</Step>
|
||||
<Step title="Create a Push Consumer">
|
||||
Create a push consumer that will capture posts from your database and deliver them to your local endpoint:
|
||||
|
||||
1. Navigate to the **Consumers** tab and click the **Create Consumer** button.
|
||||
2. Select your `posts` table (i.e `public.posts`).
|
||||
3. You want to ensure that every post receives an embedding - and that embeddings are updated as posts are updated. To do this, select to process **Rows** and click **Continue**.
|
||||
<Note>
|
||||
You can also use **changes** for this particular use case, but **rows** comes with some nice replay and backfill features.
|
||||
</Note>
|
||||
4. You'll now set the sort and filter for the consumer. For this guide, we'll sort by `updated_at` and start at the beginning of the table. We won't apply any filters:
|
||||
<Frame>
|
||||
<img src="/images/sequin-sort-and-filter.png" alt="Consumer Sort and Filter" />
|
||||
</Frame>
|
||||
5. On the next screen, select **Push** to have Sequin send the events to your webhook URL. Click **Continue**.
|
||||
6. Now, give your consumer a name (i.e. `posts_push_consumer`) and in the **HTTP Endpoint** section select the `local_endpoint` you created above. Add the exact API route you created in the previous step (i.e. `/api/create-embedding-for-post`):
|
||||
<Frame>
|
||||
<img src="/images/sequin-consumer-config.png" alt="Consumer Endpoint" />
|
||||
</Frame>
|
||||
7. Click the **Create Consumer** button.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Check>
|
||||
Your Sequin consumer is now created and ready to send events to your API endpoint.
|
||||
</Check>
|
||||
|
||||
## Test end-to-end
|
||||
|
||||
<Steps titleSize="h3">
|
||||
<Step title="Spin up you dev environment">
|
||||
1. The Next.js app is running: `npm run dev`
|
||||
2. The Trigger.dev dev server is running `npx trigger.dev@latest dev`
|
||||
3. The Sequin tunnel is running: `sequin tunnel --ports=3001:local_endpoint`
|
||||
</Step>
|
||||
<Step title="Create a new post in your database">
|
||||
|
||||
```sql
|
||||
insert into
|
||||
posts (title, body, author)
|
||||
values
|
||||
(
|
||||
'The Future of AI',
|
||||
'An insightful look into how artificial intelligence is shaping the future of technology and society.',
|
||||
'Alice H Johnson'
|
||||
);
|
||||
```
|
||||
</Step>
|
||||
<Step title="Trace the change in the Sequin dashboard">
|
||||
In the Sequin console, navigate to the [**Trace**](https://console.sequinstream.com/trace) tab and confirm that Sequin delivered the event to your local endpoint:
|
||||
<Frame>
|
||||
<img src="/images/sequin-trace.png" alt="Trace Event" />
|
||||
</Frame>
|
||||
</Step>
|
||||
|
||||
<Step title="Confirm the event was received by your endpoint">
|
||||
In your local terminal, you should see a `200` response in your Next.js app:
|
||||
|
||||
```bash
|
||||
POST /api/create-embedding-for-post 200 in 262ms
|
||||
```
|
||||
</Step>
|
||||
<Step title="Observe the task run in the Trigger.dev dashboard">
|
||||
Finally, in the Trigger.dev dashboard, navigate to the [**Runs**](https://trigger.dev/runs) tab and confirm that the task run completed successfully:
|
||||
|
||||
<Frame>
|
||||
<img src="/images/sequin-final-run.png" alt="Task run" />
|
||||
</Frame>
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Check>
|
||||
Every time a post is created or updated, Sequin will deliver the row payload to your API endpoint and Trigger.dev will run the `create-embedding-for-post` task.
|
||||
</Check>
|
||||
|
||||
## Next steps
|
||||
|
||||
With Sequin and Trigger.dev, every post in your database will now have an embedding. This is a simple example of how you can trigger long-running tasks on database changes.
|
||||
|
||||
From here, add error handling and deploy to production:
|
||||
|
||||
- Add [retries](/errors-retrying) to your Trigger.dev task to ensure that any errors are captured and logged.
|
||||
- Deploy to [production](/guides/frameworks/nextjs#deploying-your-task-to-trigger-dev) and update your Sequin consumer to point to your production database and endpoint.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 204 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 516 KiB |
@@ -0,0 +1,145 @@
|
||||
<svg width="800" height="250" viewBox="0 0 800 250" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="send-with-sequin">
|
||||
<g id="Frame 8">
|
||||
<g id="Group 2">
|
||||
<g id="insert">
|
||||
<rect x="9.01221" y="20" width="100" height="100" rx="10" fill="#16181F"/>
|
||||
<rect x="8.01221" y="19" width="102" height="102" rx="11" stroke="#919CF9" stroke-opacity="0.3" stroke-width="2"/>
|
||||
<path id="Vector" d="M38.0122 41.2308C38.0122 43.5672 34.2063 45.4615 29.5122 45.4615C24.8181 45.4615 21.0122 43.5672 21.0122 41.2308M38.0122 41.2308C38.0122 38.8944 34.2063 37 29.5122 37C24.8181 37 21.0122 38.8944 21.0122 41.2308M38.0122 41.2308V52.7692C38.0122 55.1056 34.2063 57 29.5122 57C24.8181 57 21.0122 55.1056 21.0122 52.7692V41.2308M38.0122 41.2308V45.0769M21.0122 41.2308V45.0769M38.0122 45.0769V48.9231C38.0122 51.2595 34.2063 53.1538 29.5122 53.1538C24.8181 53.1538 21.0122 51.2595 21.0122 48.9231V45.0769M38.0122 45.0769C38.0122 47.4133 34.2063 49.3077 29.5122 49.3077C24.8181 49.3077 21.0122 47.4133 21.0122 45.0769" stroke="#919CF9" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<g id="Code snippet">
|
||||
<text fill="#FF79C6" xml:space="preserve" style="white-space: pre" font-family="DM Mono" font-size="15" letter-spacing="0em"><tspan x="21.0122" y="83.615">INSERT </tspan></text>
|
||||
<text fill="#F8F8F2" xml:space="preserve" style="white-space: pre" font-family="DM Mono" font-size="10" letter-spacing="0em"><tspan x="44.9966" y="98.615"> posts</tspan></text>
|
||||
<text fill="#FF79C6" xml:space="preserve" style="white-space: pre" font-family="DM Mono" font-size="10" letter-spacing="0em"><tspan x="21.0122" y="98.615">INTO</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g id="wal">
|
||||
<rect x="106.012" y="104" width="62" height="25" rx="10" transform="rotate(-90 106.012 104)" fill="#919CF9" fill-opacity="0.7"/>
|
||||
<text id="W A L" fill="white" xml:space="preserve" style="white-space: pre" font-family="DM Mono" font-size="10" font-weight="500" letter-spacing="0em"><tspan x="115.514" y="66.41">W </tspan><tspan x="115.514" y="76.41">A </tspan><tspan x="115.514" y="86.41">L</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Group 2_2">
|
||||
<g id="insert_2">
|
||||
<rect x="9.01221" y="130" width="100" height="100" rx="10" fill="#16181F"/>
|
||||
<rect x="8.01221" y="129" width="102" height="102" rx="11" stroke="#919CF9" stroke-opacity="0.3" stroke-width="2"/>
|
||||
<path id="Vector_2" d="M38.0122 151.231C38.0122 153.567 34.2063 155.462 29.5122 155.462C24.8181 155.462 21.0122 153.567 21.0122 151.231M38.0122 151.231C38.0122 148.894 34.2063 147 29.5122 147C24.8181 147 21.0122 148.894 21.0122 151.231M38.0122 151.231V162.769C38.0122 165.106 34.2063 167 29.5122 167C24.8181 167 21.0122 165.106 21.0122 162.769V151.231M38.0122 151.231V155.077M21.0122 151.231V155.077M38.0122 155.077V158.923C38.0122 161.259 34.2063 163.154 29.5122 163.154C24.8181 163.154 21.0122 161.259 21.0122 158.923V155.077M38.0122 155.077C38.0122 157.413 34.2063 159.308 29.5122 159.308C24.8181 159.308 21.0122 157.413 21.0122 155.077" stroke="#919CF9" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<g id="Code snippet_2">
|
||||
<text fill="#FF79C6" xml:space="preserve" style="white-space: pre" font-family="DM Mono" font-size="15" letter-spacing="0em"><tspan x="21.0122" y="193.615">Update </tspan></text>
|
||||
<text fill="#F8F8F2" xml:space="preserve" style="white-space: pre" font-family="DM Mono" font-size="10" letter-spacing="0em"><tspan x="21.0122" y="208.615">posts </tspan></text>
|
||||
<text fill="#FF79C6" xml:space="preserve" style="white-space: pre" font-family="DM Mono" font-size="10" letter-spacing="0em"><tspan x="56.9888" y="208.615">set</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g id="wal_2">
|
||||
<rect x="106.012" y="214" width="62" height="25" rx="10" transform="rotate(-90 106.012 214)" fill="#919CF9" fill-opacity="0.7"/>
|
||||
<text id="W A L_2" fill="white" xml:space="preserve" style="white-space: pre" font-family="DM Mono" font-size="10" font-weight="500" letter-spacing="0em"><tspan x="115.514" y="176.41">W </tspan><tspan x="115.514" y="186.41">A </tspan><tspan x="115.514" y="196.41">L</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Group 8">
|
||||
<path id="arrow" d="M197.094 101.386L197.135 102.386L197.135 102.386L197.094 101.386ZM208.391 101.622C208.765 101.215 208.738 100.583 208.332 100.209L201.707 94.1162C201.301 93.7423 200.668 93.7688 200.294 94.1753C199.92 94.5818 199.947 95.2144 200.353 95.5883L206.242 101.004L200.826 106.892C200.452 107.299 200.479 107.931 200.885 108.305C201.292 108.679 201.924 108.653 202.298 108.246L208.391 101.622ZM153.529 58.9797L154.015 58.1056L153.529 58.9797ZM167.734 78.3877L166.754 78.5864L166.754 78.5864L167.734 78.3877ZM197.135 102.386L207.696 101.944L207.613 99.9457L197.052 100.387L197.135 102.386ZM151.119 58.7845L153.043 59.8539L154.015 58.1056L152.09 57.0362L151.119 58.7845ZM153.043 59.8539C160.133 63.7927 165.143 70.6377 166.754 78.5864L168.715 78.1891C166.987 69.6671 161.616 62.3284 154.015 58.1056L153.043 59.8539ZM197.052 100.387C183.435 100.957 171.422 91.5466 168.715 78.1891L166.754 78.5864C169.657 92.9072 182.536 102.996 197.135 102.386L197.052 100.387Z" fill="black" class="dark:fill-white"/>
|
||||
<path id="arrow_2" d="M194.542 147.388L194.351 146.406L194.351 146.406L194.542 147.388ZM207.392 144.17C207.85 144.478 207.971 145.1 207.662 145.558L202.63 153.019C202.321 153.477 201.699 153.598 201.241 153.289C200.784 152.98 200.663 152.359 200.972 151.901L205.445 145.268L198.813 140.795C198.355 140.486 198.234 139.865 198.543 139.407C198.852 138.949 199.473 138.828 199.931 139.137L207.392 144.17ZM168.163 173.557L167.183 173.358L167.183 173.358L168.163 173.557ZM194.351 146.406L206.642 144.017L207.024 145.98L194.733 148.37L194.351 146.406ZM151.118 195.279C159.408 190.673 165.3 182.65 167.183 173.358L169.143 173.755C167.143 183.623 160.889 192.139 152.089 197.027L151.118 195.279ZM194.733 148.37C181.852 150.874 171.75 160.895 169.143 173.755L167.183 173.358C169.951 159.704 180.675 149.065 194.351 146.406L194.733 148.37Z" fill="black" class="dark:fill-white"/>
|
||||
</g>
|
||||
<g id="event">
|
||||
<rect x="217.655" y="75" width="125" height="100" rx="10" fill="#16181F"/>
|
||||
<rect x="216.655" y="74" width="127" height="102" rx="11" stroke="#919CF9" stroke-opacity="0.3" stroke-width="2"/>
|
||||
<g id="NEW Sequin Logo - WHITE 2" clip-path="url(#clip0_68_2)">
|
||||
<path id="Vector_3" d="M244.197 101.132C244.197 93.0429 233.612 95.8867 233.612 91.7158C233.612 90.0095 234.919 89.0616 236.879 89.0616C238.905 89.0616 240.211 90.1359 240.211 92.0002H244.099C244.099 88.1769 241.094 85.5859 236.879 85.5859C232.729 85.5859 229.756 88.0505 229.756 91.7158C229.756 99.6152 240.277 96.2342 240.277 101.132C240.277 102.933 239.035 103.912 237.01 103.912C234.919 103.912 233.612 102.838 233.612 100.974H229.724C229.724 104.797 232.762 107.388 237.01 107.388C241.192 107.388 244.197 104.86 244.197 101.132ZM262.568 99.1728C262.568 94.37 259.04 90.9574 254.074 90.9574C249.108 90.9574 245.579 94.37 245.579 99.1728C245.579 104.007 249.108 107.388 254.074 107.388C257.733 107.388 260.935 105.619 261.85 102.617H257.668C256.851 103.786 255.544 104.165 254.074 104.165C251.656 104.165 249.957 102.806 249.434 100.563H262.438C262.503 100.121 262.568 99.6467 262.568 99.1728ZM254.074 94.1804C256.328 94.1804 257.994 95.4127 258.55 97.4665H249.532C250.12 95.4127 251.787 94.1804 254.074 94.1804ZM272.292 90.9574C267.326 90.9574 263.798 94.3384 263.798 99.1728C263.798 103.976 267.326 107.388 272.292 107.388C274.155 107.388 275.756 106.788 276.997 105.745V112.444H280.787V91.2734H276.997V92.6005C275.756 91.5262 274.155 90.9574 272.292 90.9574ZM272.292 94.3068C275.135 94.3068 276.997 96.2342 276.997 99.1728C276.997 102.111 275.135 104.039 272.292 104.039C269.417 104.039 267.522 102.111 267.522 99.1728C267.522 96.2342 269.417 94.3068 272.292 94.3068ZM282.854 100.753C282.854 104.639 285.566 107.388 289.421 107.388C291.022 107.388 292.395 106.819 293.407 105.84V107.072H297.132V91.2734H293.407V100.753C293.407 102.712 292.035 104.039 290.01 104.039C287.984 104.039 286.612 102.712 286.612 100.753V91.2734H282.854V100.753ZM299.255 89.3776H303.045V85.9019H299.255V89.3776ZM299.255 107.072H303.045V91.2734H299.255V107.072ZM305.126 107.072H308.916V97.5929C308.916 95.6339 310.223 94.3068 312.314 94.3068C314.307 94.3068 315.679 95.6339 315.679 97.5929V107.072H319.436V97.5929C319.436 93.7064 316.725 90.9574 312.869 90.9574C311.301 90.9574 309.929 91.4946 308.916 92.4741V91.2734H305.126V107.072Z" fill="white"/>
|
||||
</g>
|
||||
<text id="Code snippet_3" fill="#BD93F9" xml:space="preserve" style="white-space: pre" font-family="DM Mono" font-size="14" letter-spacing="0em"><tspan x="229.655" y="137.728">Capture & </tspan><tspan x="229.655" y="158.728">Send Webhook</tspan></text>
|
||||
</g>
|
||||
<path id="arrow_3" d="M409.362 125.707C409.752 125.317 409.752 124.683 409.362 124.293L402.998 117.929C402.607 117.538 401.974 117.538 401.584 117.929C401.193 118.319 401.193 118.953 401.584 119.343L407.241 125L401.584 130.657C401.193 131.047 401.193 131.681 401.584 132.071C401.974 132.462 402.607 132.462 402.998 132.071L409.362 125.707ZM352.655 126H408.655V124H352.655V126Z" fill="black" class="dark:fill-white"/>
|
||||
<g id="event_2">
|
||||
<rect x="418.655" y="75" width="171.333" height="100" rx="10" fill="#16181F"/>
|
||||
<rect x="417.655" y="74" width="173.333" height="102" rx="11" stroke="#919CF9" stroke-opacity="0.3" stroke-width="2"/>
|
||||
<g id="Frame" clip-path="url(#clip1_68_2)">
|
||||
<path id="Vector_4" d="M468.653 87.4779H457.012H457.472V90.6516H461.391V104.308H464.709V90.6516H468.653V87.4779Z" fill="url(#paint0_linear_68_2)"/>
|
||||
<path id="Vector_5" d="M471.827 94.3543V92.2866H468.725V104.308H471.827V98.562C471.827 96.0374 473.871 95.3161 475.482 95.5084V92.0462C473.967 92.0462 472.452 92.7194 471.827 94.3543Z" fill="url(#paint1_linear_68_2)"/>
|
||||
<path id="Vector_6" d="M478.801 90.844C479.859 90.844 480.725 89.9784 480.725 88.9446C480.725 87.9107 479.859 87.0211 478.801 87.0211C477.767 87.0211 476.901 87.9107 476.901 88.9446C476.901 89.9784 477.767 90.844 478.801 90.844ZM477.262 104.308H480.364V92.2866H477.262V104.308Z" fill="url(#paint2_linear_68_2)"/>
|
||||
<path id="Vector_7" d="M492.147 92.2866V93.7773C491.305 92.6473 490.007 91.95 488.299 91.95C484.885 91.95 482.312 94.739 482.312 98.1051C482.312 101.495 484.885 104.26 488.299 104.26C490.007 104.26 491.305 103.563 492.147 102.433V103.731C492.147 105.631 490.945 106.689 488.997 106.689C487.145 106.689 486.352 105.943 485.847 105.006L483.202 106.52C484.26 108.468 486.328 109.454 488.901 109.454C492.075 109.454 495.177 107.674 495.177 103.731V92.2866H492.147ZM488.78 101.399C486.833 101.399 485.414 100.029 485.414 98.1051C485.414 96.2057 486.833 94.8352 488.78 94.8352C490.728 94.8352 492.147 96.2057 492.147 98.1051C492.147 100.029 490.728 101.399 488.78 101.399Z" fill="url(#paint3_linear_68_2)"/>
|
||||
<path id="Vector_8" d="M506.935 92.2866V93.7773C506.093 92.6473 504.795 91.95 503.088 91.95C499.673 91.95 497.1 94.739 497.1 98.1051C497.1 101.495 499.673 104.26 503.088 104.26C504.795 104.26 506.093 103.563 506.935 102.433V103.731C506.935 105.631 505.733 106.689 503.785 106.689C501.933 106.689 501.14 105.943 500.635 105.006L497.99 106.52C499.048 108.468 501.116 109.454 503.689 109.454C506.863 109.454 509.965 107.674 509.965 103.731V92.2866H506.935ZM503.569 101.399C501.621 101.399 500.202 100.029 500.202 98.1051C500.202 96.2057 501.621 94.8352 503.569 94.8352C505.516 94.8352 506.935 96.2057 506.935 98.1051C506.935 100.029 505.516 101.399 503.569 101.399Z" fill="url(#paint4_linear_68_2)"/>
|
||||
<path id="Vector_9" d="M515.135 99.5717H524.2C524.272 99.163 524.321 98.7542 524.321 98.2975C524.321 94.7631 521.796 91.95 518.237 91.95C514.462 91.95 511.889 94.715 511.889 98.2975C511.889 101.88 514.438 104.645 518.477 104.645C520.786 104.645 522.589 103.707 523.719 102.072L521.219 100.63C520.69 101.327 519.728 101.832 518.525 101.832C516.89 101.832 515.568 101.159 515.135 99.5717ZM515.087 97.1674C515.448 95.6286 516.578 94.739 518.237 94.739C519.535 94.739 520.834 95.4363 521.219 97.1674H515.087Z" fill="url(#paint5_linear_68_2)"/>
|
||||
<path id="Vector_10" d="M529.263 94.3543V92.2866H526.161V104.308H529.263V98.562C529.263 96.0374 531.306 95.3161 532.918 95.5084V92.0462C531.403 92.0462 529.888 92.7194 529.263 94.3543Z" fill="url(#paint6_linear_68_2)"/>
|
||||
<path id="Vector_11" d="M534.096 104.621C535.226 104.621 536.14 103.707 536.14 102.577C536.14 101.447 535.226 100.534 534.096 100.534C532.965 100.534 532.052 101.447 532.052 102.577C532.052 103.707 532.965 104.621 534.096 104.621Z" fill="url(#paint7_linear_68_2)"/>
|
||||
<path id="Vector_12" d="M547.128 87.4781V93.7054C546.262 92.5994 544.988 91.9502 543.232 91.9502C540.011 91.9502 537.366 94.7152 537.366 98.2976C537.366 101.88 540.011 104.645 543.232 104.645C544.988 104.645 546.262 103.996 547.128 102.89V104.308H550.231V87.4781H547.128ZM543.81 101.688C541.886 101.688 540.468 100.317 540.468 98.2976C540.468 96.278 541.886 94.9075 543.81 94.9075C545.71 94.9075 547.128 96.278 547.128 98.2976C547.128 100.317 545.71 101.688 543.81 101.688Z" fill="url(#paint8_linear_68_2)"/>
|
||||
<path id="Vector_13" d="M555.208 99.5719H564.273C564.345 99.1632 564.393 98.7545 564.393 98.2976C564.393 94.7633 561.869 91.9502 558.31 91.9502C554.535 91.9502 551.962 94.7152 551.962 98.2976C551.962 101.88 554.511 104.645 558.551 104.645C560.858 104.645 562.662 103.707 563.792 102.072L561.292 100.63C560.763 101.327 559.801 101.832 558.598 101.832C556.964 101.832 555.641 101.159 555.208 99.5719ZM555.16 97.1676C555.521 95.6288 556.651 94.7392 558.31 94.7392C559.608 94.7392 560.907 95.4365 561.292 97.1676H555.16Z" fill="url(#paint9_linear_68_2)"/>
|
||||
<path id="Vector_14" d="M573.748 92.2868L570.814 100.702L567.904 92.2868H564.49L569.058 104.308H572.593L577.163 92.2868H573.748Z" fill="url(#paint10_linear_68_2)"/>
|
||||
<path id="Vector_15" d="M437.514 92.583L442.155 84.5468L453.655 104.463H430.655L435.295 96.4268L438.578 98.3219L437.22 100.673H447.089L442.155 92.127L440.797 94.4782L437.514 92.583Z" fill="url(#paint11_linear_68_2)"/>
|
||||
</g>
|
||||
<text id="Code snippet_4" fill="#50FA7B" xml:space="preserve" style="white-space: pre" font-family="DM Mono" font-size="15" letter-spacing="0em"><tspan x="430.655" y="136.615">Trigger job via </tspan><tspan x="430.655" y="159.615">API route</tspan></text>
|
||||
</g>
|
||||
<path id="arrow_4" d="M656.695 125.707C657.085 125.317 657.085 124.683 656.695 124.293L650.331 117.929C649.94 117.538 649.307 117.538 648.917 117.929C648.526 118.319 648.526 118.953 648.917 119.343L654.574 125L648.917 130.657C648.526 131.047 648.526 131.681 648.917 132.071C649.307 132.462 649.94 132.462 650.331 132.071L656.695 125.707ZM599.988 126H655.988V124H599.988V126Z" fill="black" class="dark:fill-white"/>
|
||||
<g id="event_3">
|
||||
<rect x="665.988" y="75" width="125" height="100" rx="10" fill="#16181F"/>
|
||||
<rect x="664.988" y="74" width="127" height="102" rx="11" stroke="#919CF9" stroke-opacity="0.3" stroke-width="2"/>
|
||||
<g id="brain-solid 1" clip-path="url(#clip2_68_2)">
|
||||
<path id="Vector_16" d="M686.972 84.5C688.481 84.5 689.707 85.7256 689.707 87.2344V106.766C689.707 108.274 688.481 109.5 686.972 109.5C685.561 109.5 684.399 108.431 684.252 107.054C683.999 107.122 683.73 107.156 683.457 107.156C681.733 107.156 680.332 105.755 680.332 104.031C680.332 103.67 680.395 103.318 680.507 102.996C679.033 102.439 677.988 101.014 677.988 99.3438C677.988 97.7861 678.901 96.4385 680.224 95.8135C679.799 95.2812 679.55 94.6074 679.55 93.875C679.55 92.376 680.605 91.126 682.011 90.8184C681.933 90.5498 681.894 90.2617 681.894 89.9688C681.894 88.5088 682.9 87.2783 684.252 86.9365C684.399 85.5693 685.561 84.5 686.972 84.5ZM694.003 84.5C695.415 84.5 696.572 85.5693 696.723 86.9365C698.081 87.2783 699.082 88.5039 699.082 89.9688C699.082 90.2617 699.042 90.5498 698.964 90.8184C700.371 91.1211 701.425 92.376 701.425 93.875C701.425 94.6074 701.176 95.2812 700.751 95.8135C702.075 96.4385 702.988 97.7861 702.988 99.3438C702.988 101.014 701.943 102.439 700.468 102.996C700.581 103.318 700.644 103.67 700.644 104.031C700.644 105.755 699.243 107.156 697.519 107.156C697.246 107.156 696.977 107.122 696.723 107.054C696.577 108.431 695.415 109.5 694.003 109.5C692.495 109.5 691.269 108.274 691.269 106.766V87.2344C691.269 85.7256 692.495 84.5 694.003 84.5Z" fill="#8BE9FD"/>
|
||||
</g>
|
||||
<text id="Code snippet_5" fill="#8BE9FD" xml:space="preserve" style="white-space: pre" font-family="DM Mono" font-size="15" letter-spacing="0em"><tspan x="677.988" y="136.115">Create </tspan><tspan x="677.988" y="159.115">Embedding</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_68_2" x1="494.964" y1="113.625" x2="494.964" y2="87.0211" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#41FF54"/>
|
||||
<stop offset="1" stop-color="#E7FF52"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_68_2" x1="494.964" y1="113.625" x2="494.964" y2="87.0211" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#41FF54"/>
|
||||
<stop offset="1" stop-color="#E7FF52"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_68_2" x1="494.965" y1="113.625" x2="494.965" y2="87.0211" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#41FF54"/>
|
||||
<stop offset="1" stop-color="#E7FF52"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_68_2" x1="494.965" y1="113.625" x2="494.965" y2="87.0211" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#41FF54"/>
|
||||
<stop offset="1" stop-color="#E7FF52"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_68_2" x1="494.964" y1="113.625" x2="494.964" y2="87.0211" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#41FF54"/>
|
||||
<stop offset="1" stop-color="#E7FF52"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_68_2" x1="494.964" y1="113.625" x2="494.964" y2="87.0211" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#41FF54"/>
|
||||
<stop offset="1" stop-color="#E7FF52"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint6_linear_68_2" x1="494.965" y1="113.625" x2="494.965" y2="87.0211" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#41FF54"/>
|
||||
<stop offset="1" stop-color="#E7FF52"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint7_linear_68_2" x1="554.607" y1="111.6" x2="557.837" y2="89.3744" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#2563EB"/>
|
||||
<stop offset="1" stop-color="#A855F7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint8_linear_68_2" x1="554.606" y1="111.6" x2="557.837" y2="89.3744" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#2563EB"/>
|
||||
<stop offset="1" stop-color="#A855F7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint9_linear_68_2" x1="554.606" y1="111.6" x2="557.837" y2="89.3744" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#2563EB"/>
|
||||
<stop offset="1" stop-color="#A855F7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint10_linear_68_2" x1="554.606" y1="111.6" x2="557.837" y2="89.3744" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#2563EB"/>
|
||||
<stop offset="1" stop-color="#A855F7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint11_linear_68_2" x1="449.277" y1="104.463" x2="449.062" y2="90.4029" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#41FF54"/>
|
||||
<stop offset="1" stop-color="#E7FF52"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_68_2">
|
||||
<rect width="90" height="26.9072" fill="white" transform="translate(229.655 85.5464)"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip1_68_2">
|
||||
<rect width="147.333" height="26" fill="white" transform="translate(430.655 84)"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip2_68_2">
|
||||
<rect width="25" height="25" fill="white" transform="translate(677.988 84.5)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.dark\:fill-white {
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 139 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 310 KiB |
@@ -259,6 +259,7 @@
|
||||
"guides/frameworks/nodejs",
|
||||
"guides/frameworks/prisma",
|
||||
"guides/frameworks/remix",
|
||||
"guides/frameworks/sequin",
|
||||
{
|
||||
"group": "Supabase",
|
||||
"icon": "bolt",
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<Card
|
||||
icon={
|
||||
<svg width="148" height="46" viewBox="0 0 148 46" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M23.9146 26.5013C23.9146 12.7469 6.50676 17.5825 6.50676 10.4904C6.50676 7.58904 8.65591 5.97719 11.8796 5.97719C15.2107 5.97719 17.3598 7.80395 17.3598 10.9739H23.7535C23.7535 4.47284 18.8105 0.0671387 11.8796 0.0671387C5.05613 0.0671387 0.166887 4.25792 0.166887 10.4904C0.166887 23.9223 17.4673 18.1735 17.4673 26.5013C17.4673 29.5638 15.4256 31.2293 12.0945 31.2293C8.65591 31.2293 6.50676 29.4026 6.50676 26.2326H0.113159C0.113159 32.7337 5.10988 37.1394 12.0945 37.1394C18.9717 37.1394 23.9146 32.8412 23.9146 26.5013ZM54.1247 23.1701C54.1247 15.0035 48.3224 9.20088 40.1558 9.20088C31.9889 9.20088 26.1863 15.0035 26.1863 23.1701C26.1863 31.3905 31.9889 37.1394 40.1558 37.1394C46.1732 37.1394 51.4384 34.1307 52.9426 29.0265H46.0658C44.7223 31.0144 42.5735 31.6592 40.1558 31.6592C36.1797 31.6592 33.3859 29.3489 32.5262 25.5342H53.9098C54.0172 24.782 54.1247 23.9761 54.1247 23.1701ZM40.1558 14.6811C43.8629 14.6811 46.6029 16.7765 47.5164 20.2689H32.6874C33.6545 16.7765 36.3946 14.6811 40.1558 14.6811ZM70.115 9.20088C61.9484 9.20088 56.1461 14.9498 56.1461 23.1701C56.1461 31.3368 61.9484 37.1394 70.115 37.1394C73.1777 37.1394 75.8102 36.1186 77.852 34.3456V45.736H84.0843V9.73818H77.852V11.9947C75.8102 10.168 73.1777 9.20088 70.115 9.20088ZM70.115 14.8961C74.7894 14.8961 77.852 18.1735 77.852 23.1701C77.852 28.1668 74.7894 31.4442 70.115 31.4442C65.387 31.4442 62.271 28.1668 62.271 23.1701C62.271 18.1735 65.387 14.8961 70.115 14.8961ZM87.4835 25.8565C87.4835 32.4651 91.943 37.1394 98.2828 37.1394C100.916 37.1394 103.172 36.1723 104.838 34.5067V36.6021H110.963V9.73818H104.838V25.8565C104.838 29.1877 102.581 31.4442 99.2499 31.4442C95.9187 31.4442 93.6621 29.1877 93.6621 25.8565V9.73818H87.4835V25.8565ZM114.454 6.51448H120.686V0.604419H114.454V6.51448ZM114.454 36.6021H120.686V9.73818H114.454V36.6021ZM124.108 36.6021H130.34V20.4837C130.34 17.1526 132.489 14.8961 135.928 14.8961C139.206 14.8961 141.462 17.1526 141.462 20.4837V36.6021H147.641V20.4837C147.641 13.8752 143.181 9.20088 136.842 9.20088C134.263 9.20088 132.006 10.1143 130.34 11.7798V9.73818H124.108V36.6021Z" fill="white"/>
|
||||
</svg>
|
||||
}
|
||||
href="/guides/frameworks/sequin"
|
||||
|
||||
/>
|
||||
Reference in New Issue
Block a user