-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1730 from fireship-io/stripe-saas
stripe for saas full course
- Loading branch information
Showing
33 changed files
with
1,567 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
--- | ||
lastmod: 2024-03-24T11:11:30-09:00 | ||
title: Stripe for SaaS | ||
description: Accept Payments in your Software-as-a-Service Product with Stripe | ||
weight: 0 | ||
type: courses | ||
vimeo: 927652411 | ||
author: Jeff Delaney | ||
tags: | ||
- stripe | ||
- pro | ||
- typescript | ||
|
||
stack: | ||
- stripe | ||
- nextjs | ||
- supabase | ||
--- | ||
|
||
**Stripe for SaaS Full Course** is a hands-on tutorial where you will build a monetized web app with [Stripe](https://stripe.com/), [Next.js](https://nextjs.org/) and [Supabase](https://supabase.com/). | ||
|
||
## ⚡ What will I learn? | ||
|
||
- 💵 Everything you need to build complex payment flows with Stripe | ||
- 💷 One-time payments | ||
- 💶 Recurring subscriptions | ||
- ⏱️ Metered pay-as-you-go billing | ||
- 🎣 Handle and test Stripe webhooks locally | ||
- 🤝 Payment and billing strategies for SaaS products | ||
- 🔥 Master key concepts quickly with fast-paced vidoes | ||
- ⚛️ Fullstack starter project with Next.js frontend and Supabase backend | ||
- 🧑💻 Includes all source code and project files | ||
|
||
## 🦄 What will I build? | ||
|
||
You will build a **Stock Photography Subscription SaaS Product** from scratch where users can sign up for a subscription to access a library of images. Every monetized action is tracked in Stripe and the user is billed based on usage at the end of the month. | ||
|
||
The full project demonstates how to accept payments, manage recurring subscriptions, cancellations, metereing, and more. Watch the [App Tour](/courses/stripe-saas/project-tour/) video for a full breakdown of the project. | ||
|
||
|
||
## 🤔 Is this Course Right for Me? | ||
|
||
<div class="box box-blue"> | ||
This course is intermediate level 🟦 and expects some familiarity with JavaScript and web development. The content is fast-paced and similar to my style on YouTube, but far more in-depth and should be followed in a linear format. | ||
</div> | ||
|
||
|
||
## When was the course last updated? | ||
|
||
<span class="tag tag-sm tag-pro">Updated March 26th, 2024</span> <span class="tag tag-sm tag-svelte">Next.js 14</span> <span class="tag tag-sm tag-firebase">Supabase.js 2+</span> | ||
|
||
## How do I enroll? | ||
|
||
The first few videos are *free*, so just give it try. When you reach a paid module, you will be asked to pay for a single course or upgrade to PRO. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
title: Embedded Checkout | ||
description: Create an embedded stripe checkout page | ||
weight: 40 | ||
lastmod: 2024-03-22T10:23:30-09:00 | ||
draft: false | ||
vimeo: | ||
emoji: 🎊 | ||
video_length: 3:00 | ||
chapter_start: Bonus Round | ||
--- | ||
|
||
### Coming Soon... | ||
|
||
This video is in develpment and will be available soon. Stay tuned! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
--- | ||
title: Checkout Session | ||
description: Create a Stripe Checkout Session on the server | ||
weight: 12 | ||
lastmod: 2024-03-22T10:23:30-09:00 | ||
draft: false | ||
vimeo: 927619746 | ||
emoji: 🛒 | ||
video_length: 2:31 | ||
--- | ||
|
||
### Extra Resources | ||
|
||
- Stripe Testing Cards [Link](https://docs.stripe.com/testing) | ||
|
||
### Prompt Template | ||
|
||
```text | ||
Create a POST endpoint in [SOME WEB FRAMEWORK] that creates a Stripe Checkout Session using the code below as a reference. | ||
``` | ||
|
||
### Code | ||
|
||
{{< file "ts" "src/index.ts" >}} | ||
```typescript | ||
import { serve } from '@hono/node-server' | ||
import { Hono } from 'hono' | ||
import { HTTPException } from 'hono/http-exception'; | ||
import Stripe from 'stripe'; | ||
import 'dotenv/config' | ||
|
||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); | ||
|
||
|
||
const app = new Hono() | ||
|
||
app.get('/success', (c) => { | ||
return c.text('Success!') | ||
}) | ||
|
||
app.get('/cancel', (c) => { | ||
return c.text('Hello Hono!') | ||
}) | ||
|
||
|
||
app.post('/checkout', async (c) => { | ||
|
||
|
||
try { | ||
const session = await stripe.checkout.sessions.create({ | ||
payment_method_types: ['card'], | ||
line_items: [ | ||
{ | ||
price: 'price_YOUR_PRICE_ID', | ||
quantity: 1, | ||
}, | ||
], | ||
mode: 'payment', | ||
success_url: 'http://localhost:3000/success', | ||
cancel_url: 'http://localhost:3000//cancel', | ||
}); | ||
|
||
return c.json(session); | ||
} catch (error: any) { | ||
console.error(error); | ||
throw new HTTPException(500, { message: error?.message }); | ||
} | ||
}); | ||
|
||
const port = 3000 | ||
console.log(`Server is running on port ${port}`) | ||
|
||
serve({ | ||
fetch: app.fetch, | ||
port | ||
}) | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
--- | ||
title: Environment Variables | ||
description: Add the Stripe SDK to Environemt Variables | ||
weight: 11 | ||
lastmod: 2024-03-22T10:23:30-09:00 | ||
draft: false | ||
vimeo: 927619770 | ||
emoji: 🔐 | ||
video_length: 3:01 | ||
--- | ||
|
||
### Commands | ||
|
||
Create a .env file and install the dotenv and stripe packages. | ||
|
||
```bash | ||
touch .env | ||
npm i dotenv stripe | ||
``` | ||
|
||
### Prompt Template | ||
|
||
```text | ||
Configure Stripe environemt variables in [SOME WEB FRAMEWORK] using the code below as a reference. | ||
Use the environment variables to initialize the Stripe SDK. | ||
``` | ||
|
||
### Code | ||
|
||
{{< file "cog" ".env" >}} | ||
```text | ||
STRIPE_PUBLISHABLE_KEY=pk_test_ | ||
STRIPE_SECRET_KEY=sk_test_ | ||
STRIPE_WEBHOOK_SECRET=whsec_ | ||
``` | ||
|
||
{{< file "ts" "src/index.ts" >}} | ||
```typescript | ||
import { serve } from '@hono/node-server' | ||
import { Hono } from 'hono' | ||
import Stripe from 'stripe'; | ||
import 'dotenv/config' | ||
|
||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); | ||
|
||
|
||
const app = new Hono() | ||
|
||
const port = 3000 | ||
console.log(`Server is running on port ${port}`) | ||
|
||
serve({ | ||
fetch: app.fetch, | ||
port | ||
}) | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
--- | ||
title: Checkout Frontend | ||
description: Trigger a Stripe Checkout Session from a web frontend | ||
weight: 13 | ||
lastmod: 2024-03-22T10:23:30-09:00 | ||
draft: false | ||
vimeo: 927619796 | ||
emoji: 💻 | ||
video_length: 1:33 | ||
--- | ||
|
||
|
||
### Prompt Template | ||
|
||
```text | ||
Create a GET endpoint on the "/" route in [SOME WEB FRAMEWORK] that renders an HTML page. | ||
The webpage should contain a button that triggers a POST request to the /checkout endpoint using the browser fetch API. | ||
``` | ||
|
||
### Code | ||
|
||
{{< file "ts" "src/index.ts" >}} | ||
```typescript | ||
import { serve } from '@hono/node-server' | ||
import { Hono } from 'hono' | ||
import { HTTPException } from 'hono/http-exception'; | ||
import Stripe from 'stripe'; | ||
import 'dotenv/config' | ||
|
||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); | ||
|
||
|
||
const app = new Hono() | ||
|
||
app.get('/', (c) => { | ||
const html = ` | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Checkout</title> | ||
<script src="https://js.stripe.com/v3/"></script> | ||
</head> | ||
<body> | ||
<h1>Checkout</h1> | ||
<button id="checkoutButton">Checkout</button> | ||
<script> | ||
const checkoutButton = document.getElementById('checkoutButton'); | ||
checkoutButton.addEventListener('click', async () => { | ||
const response = await fetch('/checkout', { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
}); | ||
const { id } = await response.json(); | ||
const stripe = Stripe('${process.env.STRIPE_PUBLISHABLE_KEY}'); | ||
await stripe.redirectToCheckout({ sessionId: id }); | ||
}); | ||
</script> | ||
</body> | ||
</html> | ||
`; | ||
return c.html(html); | ||
}) | ||
|
||
const port = 3000 | ||
console.log(`Server is running on port ${port}`) | ||
|
||
serve({ | ||
fetch: app.fetch, | ||
port | ||
}) | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
--- | ||
title: Hono Backend | ||
description: Create a web server with Node.js & Hono | ||
weight: 10 | ||
lastmod: 2024-03-22T10:23:30-09:00 | ||
draft: false | ||
vimeo: 927619817 | ||
emoji: 🏯 | ||
video_length: 3:22 | ||
free: true | ||
chapter_start: Simple Project | ||
--- | ||
|
||
### Extra Resources | ||
|
||
REST APIs in 100 Seconds: [YouTube Video](https://youtu.be/-MTSQjw5DrM) | ||
|
||
### Commands | ||
|
||
Refer to the [Hono documentation](https://hono.dev/). | ||
|
||
```bash | ||
npm create hono@latest my-app | ||
|
||
cd my-app | ||
|
||
npm run dev | ||
``` | ||
|
||
### Prompt Template | ||
|
||
```text | ||
Create a basic backend server with [SOME WEB FRAMEWORK]. | ||
Create a GET route and POST route on the root path "/" that returns a text response with a message. Adapt the Hono code below as a reference. | ||
``` | ||
|
||
### Code | ||
|
||
{{< file "ts" "src/index.ts" >}} | ||
```typescript | ||
import { serve } from '@hono/node-server' | ||
import { Hono } from 'hono' | ||
|
||
const app = new Hono() | ||
|
||
app.get('/', (c) => { | ||
c.text('GET it') | ||
}) | ||
|
||
app.post('/', (c) => { | ||
c.text('POST it') | ||
}) | ||
|
||
|
||
const port = 3000 | ||
console.log(`Server is running on port ${port}`) | ||
|
||
serve({ | ||
fetch: app.fetch, | ||
port | ||
}) | ||
``` | ||
|
Oops, something went wrong.