Skip to content

Commit

Permalink
add docs directly to the rpo
Browse files Browse the repository at this point in the history
  • Loading branch information
d-ivashchuk committed Apr 10, 2024
1 parent fd75d04 commit 4f27451
Show file tree
Hide file tree
Showing 32 changed files with 1,649 additions and 0 deletions.
128 changes: 128 additions & 0 deletions docs/essentials/authentication.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
title: "Authentication"
description: "How Cascade handles authentication and authorization."
icon: "user"
---

## Next Auth

<Tip>

Cascade is based on T3 app meaning that it uses NextAuth.js under the hood. Docs are [here](https://create.t3.gg/en/usage/next-auth).

</Tip>

This documentation is a brief overview of what is put on top of NextAuth.js to make it work with Cascade. We will focus on interesting parts!

We extend the `Session` object with some additional types to make it work with Cascade. We need to add `role` and `planId` to the user object.

```ts

declare module "next-auth" {
interface Session extends DefaultSession {
user: {
id: string;
planId: string | null;
role: Role;
} & DefaultSession["user"];
}

```
In callbacks we need to fetch the user from the database and add the `role` and `planId` to the session object. This is done to make sure that whenever you are working with Session from NextAuth.js you have all the necessary information about the user.
```ts
callbacks: {
session: async ({ session, user }) => {
const dbUser = await db.user.findUnique({
where: {
id: user.id,
},
});
return {
...session,
user: {
...session.user,
id: user.id,
planId: dbUser?.planId ?? null,
role: dbUser?.role,
},
};
},
},
```
## External services
<Tip>This section mentions something about Emails</Tip>
<Tip>This section mentions something about Error Tracking</Tip>
<Tip>This section mentions something about Background jobs</Tip>
Next Auth is a great entrypoint for other services we need to use for our SaaS.
For example, here we use events to manage the following:
- Sentry - to connect user to the Sentry error tracking, so we could easily debug it.
- Trigger.dev - to trigger a background job to send a notification when a new user signs up
- Loops - to send a welcome email to the new users.
```ts
events: {
async signIn({ user, isNewUser }) {
Sentry.setUser({ id: user.id, name: user.name, email: user.email ?? "" });
if (isNewUser) {
if (isTriggerEnabled) {
await slackNewUserNotification.invoke({
user: {
name: user.name ?? "unknown",
email: user.email ?? undefined,
id: user.id,
},
});
}
if (loops && user.email) {
await loops.sendEvent(
{
email: user.email,
},
"cascade_sign_up",
{
...(user.name && { name: user.name }),
email: user.email,
},
);
}
}
},
signOut() {
Sentry.setUser(null);
},
},
```
## Providers
Cascade comes with Discord & Google providers out of the box. You can easily add more providers by following the NextAuth.js documentation.
```ts
providers: [
DiscordProvider({
clientId: env.DISCORD_CLIENT_ID!,
clientSecret: env.DISCORD_CLIENT_SECRET!,
}),
GoogleProvider({
clientId: env.GOOGLE_CLIENT_ID!,
clientSecret: env.GOOGLE_CLIENT_SECRET!,
}),

/**
* ...add more providers here.
*
* Most other providers require a bit more work than the Discord provider. For example, the
* GitHub provider requires you to add the `refresh_token_expires_in` field to the Account
* model. Refer to the NextAuth.js docs for the provider you want to use. Example:
*
* @see https://next-auth.js.org/providers/github
*/
],
```
70 changes: 70 additions & 0 deletions docs/essentials/background-jobs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: "Background jobs"
description: "How cascade handles background jobs"
icon: "stopwatch"
---

## Background jobs tool of choice

Cascade uses [Trigger.dev](https://trigger.dev) as its background job tool of choice. Trigger.dev is a simple, reliable, and easy-to-use tool that allows you to schedule and run background jobs in a few simple steps.

## What is a background job

A background job is a task that is executed outside the normal flow of your application. It is typically used to perform tasks that are not time-sensitive, such as sending emails, sending notifications or even running a generation with AI.

Cascade uses background jobs to send Slack notifications so if you want to get notified on new users or on new payments - you need to enable Slack integration on Trigger.dev platform.

In general job definitions are pretty simple and should serve you as a good example if you want to create your own jobs.

That is the definition of a job:

```ts
export const slackNewUserNotification = triggerClient.defineJob({
id: "cascade-new-user",
name: "Cascade new user notification",
version: "0.0.1",
trigger: eventTrigger({
name: "cascade.new.user",
schema: z.object({
user: z.object({
name: z.string(),
email: z.string().email().optional(),
id: z.string(),
}),
}),
}),
integrations: {
slack,
},
run: async (payload, io, ctx) => {
await io.slack.postMessage("post message", {
channel: "C06RZ0QNP6W",
text: `🔥 *New user signed up*\n\nName: ${payload.user.name}\nEmail: ${payload.user.email}\nID:${payload.user.id}`,
});
},
```
And that's how you invoke a job:
```ts
await slackNewUserNotification.invoke({
user: {
name: user.name ?? "unknown",
email: user.email ?? undefined,
id: user.id,
},
});
```

## How to use Trigger.dev with Cascade

First, you need to create a Trigger.dev account. Once you have an account, you can create a new project and get your API key.

Populate the related environment variables in your `.env` file:

```yml
#Trigger.dev
TRIGGER_API_KEY=tr_dev_iTsdlfkjyeD33yimXrW2N
TRIGGER_API_URL=https://api.trigger.dev
NEXT_PUBLIC_TRIGGER_PUBLIC_API_KEY=pk_dev_2AO1S8wxhEfsdlkjlksjdf
```
80 changes: 80 additions & 0 deletions docs/essentials/database.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
title: "Database"
description: "How Cascade handles database"
icon: "database"
---

## Database of choice

Cascade uses [Postgres](https://www.postgresql.org/) as its database of choice. Postgres is a powerful, open source object-relational database system that uses and extends the SQL language combined with many features that safely store and scale the most complicated data workloads.

## ORM of choice

<Tip>This section mentions something about Authentication</Tip>

Cascade uses [Prisma](https://www.prisma.io/) as its ORM of choice. Prisma is a modern database toolkit that makes database access easy with an auto-generated and type-safe query builder that's tailored to your database schema.

Prisma connects really well to Postgres & NextAuth trough an adapter that makes it easy to use.

Whenever you want to make changes to database schema, you can do so by changing the schema in the `schema.prisma` file and then running `npx prisma migrate dev` to generate a migration file and apply the changes to the database.

## Database schema

Database has a few main overlapping sections, those are clearly visible in prisma schema(content of each model omitted fro brevity)

User related:

```
model Account {
...
}
model Session {
...
}
model User {
...
}
```

Payments & Subscriptions related:

```
model LemonSqueezySubscription {
...
}
model OneTimePurchase {
...
}
model Plan {
...
}
```

Feature usage related:

```
model FeatureUsage {
...
}
```
45 changes: 45 additions & 0 deletions docs/essentials/emails.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
title: "Emails"
description: "How Cascade handles marketing & transactional emails"
icon: "envelopes"
---

## Email tool of choice

Cascade uses [Loops](https://www.loops.so) for sending marketing and transactional emails. Loops is a powerful email marketing platform that allows you to send emails to your users, track their engagement, and set up funnels to automate your email marketing.

## Setup with Cascade

You need to have a Loops account to use the email feature in Cascade. If you don't have one, you can [sign up here](https://www.loops.so).

Grab your API key [from here](https://app.loops.so/settings?page=api) and add it to your `.env` file:

```
#Loops
LOOPS_API_KEY="2a2ee7a090dldskfj4bd73eb3f70a"
```

## Sending emails

Cascade implements an example of a single loop, where an email is sent to the newly created users:

<Frame>
<img src="/images/loops.jpeg" style={{ borderRadius: "0.5rem" }} />
</Frame>

When the loop is hit, it waits for a minute and then sends an email to the user. You can customize the email content and the delay between the loop and the email and set up more complex funnels as WebGLUniformLocation.\_createMdxContent

This is how you trigger loops:

```ts
await loops.sendEvent(
{
email: user.email,
},
"cascade_sign_up",
{
...(user.name && { name: user.name }),
email: user.email,
}
);
```
22 changes: 22 additions & 0 deletions docs/essentials/error-tracking.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: "Error tracking"
description: "How Cascade handles error tracking"
icon: "bug"
---

## Error tracking tool of choice

Cascade uses [Sentry](https://sentry.io) for error tracking. Sentry is an open-source error tracking tool that helps developers monitor and fix crashes in real time. It provides a comprehensive view of the errors that occur in your application, and helps you understand the impact of each error.

## Set up Sentry with Cascade

To set up Sentry with Cascade, you need to create a Sentry account and get a DSN (Data Source Name) for your project. The DSN is a unique identifier that Sentry uses to track errors in your application.

After you have gone trough the setup process, you can add all of the related variabls to your `.env` file:

```yml
#Sentry
SENTRY_DSN="https://asdjflkjsdkfljksdlfjslkdjf@o4506388280180736.ingest.us.sentry.io/4506978350399488"
SENTRY_PROJECT="YOUR_PROJECT_NAME"
SENTRY_ORG="YOUR_SENTRY_ORG"
```
Loading

0 comments on commit 4f27451

Please sign in to comment.