Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
809e982
Stripe only changes
FranjoMindek Sep 17, 2025
3df17a2
changes
FranjoMindek Sep 17, 2025
d0a2e15
further improvements
FranjoMindek Sep 17, 2025
1560833
remove typ catch
FranjoMindek Sep 21, 2025
fec25ab
split payment details funcs
FranjoMindek Sep 21, 2025
05b0fad
add awaits
FranjoMindek Sep 21, 2025
91e2f0d
name
FranjoMindek Sep 21, 2025
de70c30
Merge branch 'main' into franjo/refactor-stripe-payment-provider
FranjoMindek Sep 21, 2025
0cbe24c
formatting
FranjoMindek Sep 21, 2025
5dce0da
fix format
FranjoMindek Sep 21, 2025
4d6a64f
update
FranjoMindek Sep 21, 2025
1541759
map to switch
FranjoMindek Sep 21, 2025
dddc128
wording
FranjoMindek Sep 21, 2025
d7b5f8f
fix typo
FranjoMindek Sep 22, 2025
b764193
Merge branch 'main' into franjo/refactor-stripe-payment-provider
FranjoMindek Sep 24, 2025
d6a608a
format
FranjoMindek Sep 24, 2025
346da0f
fix diffs?
FranjoMindek Sep 24, 2025
4d9fb58
Merge remote-tracking branch 'origin/main' into franjo/refactor-strip…
FranjoMindek Sep 24, 2025
8371bd4
docs: update LLM files after documentation changes
FranjoMindek Sep 24, 2025
e5caba8
comments
FranjoMindek Oct 1, 2025
2e5ea07
wording
FranjoMindek Oct 1, 2025
f09865f
wording
FranjoMindek Oct 1, 2025
b4f80d3
wording
FranjoMindek Oct 1, 2025
2c82386
Merge branch 'main' into franjo/refactor-stripe-payment-provider
FranjoMindek Oct 1, 2025
34209ae
fix typo
FranjoMindek Oct 1, 2025
f288f9b
to 204
FranjoMindek Oct 1, 2025
0bd0b73
Merge remote-tracking branch 'origin/main' into franjo/refactor-strip…
FranjoMindek Oct 9, 2025
375cf1a
Merge remote-tracking branch 'origin/main' into franjo/refactor-strip…
FranjoMindek Oct 11, 2025
4673ec6
update env
FranjoMindek Oct 11, 2025
fb0ff94
formatting
FranjoMindek Oct 13, 2025
1adc2d0
Merge branch 'main' into franjo/refactor-stripe-payment-provider
FranjoMindek Nov 4, 2025
cd0988e
work
FranjoMindek Nov 4, 2025
a86021d
Update opensaas-sh/blog/src/content/docs/guides/deploying.mdx
FranjoMindek Nov 4, 2025
68220cc
Apply suggestion from @infomiho
FranjoMindek Nov 4, 2025
ddbe28e
Apply suggestion from @infomiho
FranjoMindek Nov 4, 2025
9a4ea86
link change
FranjoMindek Nov 4, 2025
76b9a32
Merge branch 'franjo/refactor-stripe-payment-provider' of franjo:wasp…
FranjoMindek Nov 4, 2025
5441ffc
rename
FranjoMindek Nov 4, 2025
4088bca
changes
FranjoMindek Nov 4, 2025
2262a2c
capitalize
FranjoMindek Nov 5, 2025
5fab9a3
fix trailing slash bug, formatting
FranjoMindek Nov 5, 2025
ae1b458
update diff
FranjoMindek Nov 5, 2025
8b649e0
abstract more user stuff, move to user.ts, fixes
FranjoMindek Nov 6, 2025
17586a7
diff
FranjoMindek Nov 6, 2025
631f237
fix diffs
FranjoMindek Nov 6, 2025
b9c8304
env to config
FranjoMindek Nov 6, 2025
221a549
Merge remote-tracking branch 'origin/main' into franjo/refactor-strip…
FranjoMindek Nov 6, 2025
39381df
user import
FranjoMindek Nov 10, 2025
99f01ad
move jsdoc to comment + simplify logic
FranjoMindek Nov 10, 2025
0e17428
simplify
FranjoMindek Nov 10, 2025
6928c60
improve opensaas map
FranjoMindek Nov 10, 2025
abb546c
fix comment
FranjoMindek Nov 11, 2025
5f894c0
remove logs
FranjoMindek Nov 11, 2025
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
1 change: 0 additions & 1 deletion .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ jobs:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
STRIPE_API_KEY: ${{ secrets.STRIPE_KEY }}
STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }}
STRIPE_CUSTOMER_PORTAL_URL: https://billing.stripe.com/p/login/test_8wM8x17JN7DT4zC000
PAYMENTS_HOBBY_SUBSCRIPTION_PLAN_ID: ${{ secrets.STRIPE_HOBBY_SUBSCRIPTION_PRICE_ID }}
PAYMENTS_PRO_SUBSCRIPTION_PLAN_ID: ${{ secrets.STRIPE_PRO_SUBSCRIPTION_PRICE_ID }}
PAYMENTS_CREDITS_10_PLAN_ID: ${{ secrets.STRIPE_CREDITS_PRICE_ID }}
Expand Down
8 changes: 4 additions & 4 deletions opensaas-sh/app_diff/README.md.diff
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
--- template/app/README.md
+++ opensaas-sh/app/README.md
@@ -1,16 +1,31 @@
@@ -1,6 +1,8 @@
-# <YOUR_APP_NAME>
+# opensaas.sh (demo) app

-Built with [Wasp](https://wasp.sh), based on the [Open Saas](https://opensaas.sh) template.
+This is a Wasp app based on Open Saas template with minimal modifications that make it into a demo app that showcases Open Saas's abilities.

+It is deployed to https://opensaas.sh and serves both as a landing page for Open Saas and as a demo app.
+
+It is deployed to https://opensaas.sh and serves both as a landing page for Open Saas and as a demo app.

## UI Components

This template includes [ShadCN UI](https://ui.shadcn.com/) v2 for beautiful, accessible React components. See [SHADCN_SETUP.md](./SHADCN_SETUP.md) for details on how to use ShadCN components in your app.
@@ -8,9 +10,22 @@

## Development

Expand Down
1 change: 1 addition & 0 deletions opensaas-sh/app_diff/deletions
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ src/payment/lemonSqueezy/checkoutUtils.ts
src/payment/lemonSqueezy/paymentDetails.ts
src/payment/lemonSqueezy/paymentProcessor.ts
src/payment/lemonSqueezy/webhook.ts
src/payment/lemonSqueezy/webhookPayload.ts
src/payment/webhook.ts
2 changes: 1 addition & 1 deletion opensaas-sh/app_diff/package-lock.json.diff

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions opensaas-sh/app_diff/src/analytics/stats.ts.diff
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { type DailyStats } from "wasp/entities";
import { type DailyStatsJob } from "wasp/server/jobs";
+import { SubscriptionStatus } from "../payment/plans";
import { stripe } from "../payment/stripe/stripeClient";
import { stripeClient } from "../payment/stripe/stripeClient";
import {
getDailyPageViews,
getSources,
Expand Down Expand Up @@ -38,7 +38,7 @@

const { totalViews, prevDayViewsChangePercent } = await getDailyPageViews();

@@ -176,38 +162,3 @@
@@ -177,38 +163,3 @@
// Revenue is in cents so we convert to dollars (or your main currency unit)
return totalRevenue / 100;
}
Expand Down
16 changes: 7 additions & 9 deletions opensaas-sh/app_diff/src/client/Main.css.diff
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
--- template/app/src/client/Main.css
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come we have these changes in this PR?

Should we maybe do a separate PR that only updates the diffs?

Copy link
Contributor Author

@FranjoMindek FranjoMindek Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this often happens.
We should have a CI workflow for this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of workflow were you thinking? It is something we should encode in an improvement issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A workflow which would check if generating a diff makes changes to the working directory. If it does it fails. Just to make sure your diffs are up to date with your template.

+++ opensaas-sh/app/src/client/Main.css
@@ -56,8 +56,66 @@
@@ -56,6 +56,64 @@
.border-gradient-primary > * {
background: hsl(var(--background));
}
Expand All @@ -21,8 +21,8 @@
+ hsl(var(--card)) 100%
+ );
+ }
}
+}
+
+/* Satoshi Font Family */
+@font-face {
+ font-family: "Satoshi";
Expand Down Expand Up @@ -62,11 +62,9 @@
+ font-weight: 900;
+ font-style: normal;
+ font-display: swap;
+}
+
/* third-party libraries CSS */
}

.tableCheckbox:checked ~ div span {
/* third-party libraries CSS */
@@ -176,4 +234,22 @@
body {
@apply bg-background text-foreground;
Expand All @@ -85,8 +83,8 @@
+ p {
+ @apply font-mono text-base leading-relaxed;
+ }
}
+}
+
+.navbar-maxwidth-transition {
+ transition: max-width 300ms cubic-bezier(0.4, 0, 0.2, 1);
+}
}
7 changes: 3 additions & 4 deletions opensaas-sh/app_diff/src/file-upload/operations.ts.diff
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

import * as z from "zod";
import { ensureArgsSchemaOrThrowHttpError } from "../server/validation";
@@ -37,11 +38,16 @@
@@ -37,10 +38,15 @@
throw new HttpError(401);
}

Expand All @@ -25,9 +25,8 @@
+ if (userFileLimitReached) {
+ throw new HttpError(403, 'This demo only allows 2 file uploads per user.');
+ }

+ const { fileType, fileName } = ensureArgsSchemaOrThrowHttpError(createFileInputSchema, rawArgs);
+
+ const { fileType, fileName } = ensureArgsSchemaOrThrowHttpError(createFileInputSchema, rawArgs);

return await getUploadFileSignedURLFromS3({
fileType,
fileName,
40 changes: 22 additions & 18 deletions opensaas-sh/app_diff/src/landing-page/contentSections.tsx.diff
Original file line number Diff line number Diff line change
Expand Up @@ -160,42 +160,46 @@
- avatarSrc: daBoiAvatar,
- socialUrl: "https://twitter.com/wasplang",
- quote: "I don't even know how to code. I'm just a plushie.",
- },
- {
- name: "Mr. Foobar",
- role: "Founder @ Cool Startup",
- avatarSrc: daBoiAvatar,
- socialUrl: "",
- quote: "This product makes me cooler than I already am.",
- },
- {
- name: "Jamie",
- role: "Happy Customer",
- avatarSrc: daBoiAvatar,
- socialUrl: "#",
- quote: "My cats love it!",
+ name: "Max Khamrovskyi",
+ role: "Senior Eng @ Red Hat",
+ avatarSrc:
+ "https://pbs.twimg.com/profile_images/1719397191205179392/V_QrGPSO_400x400.jpg",
+ socialUrl: "https://twitter.com/maksim36ua",
+ quote:
+ "I used Wasp to build and sell my AI-augmented SaaS app for marketplace vendors within two months!",
},
{
- name: "Mr. Foobar",
- role: "Founder @ Cool Startup",
- avatarSrc: daBoiAvatar,
- socialUrl: "",
- quote: "This product makes me cooler than I already am.",
+ },
+ {
+ name: "Jonathan Cocharan",
+ role: "Entrepreneur",
+ avatarSrc:
+ "https://pbs.twimg.com/profile_images/1950172296376639488/sZ0JIqfR_400x400.jpg",
+ socialUrl: "https://twitter.com/JonathanCochran",
+ quote:
+ "In just 6 nights... my SaaS app is live 🎉! Huge thanks to the amazing @wasplang community 🙌 for their guidance along the way. These tools are incredibly efficient 🤯!",
},
{
- name: "Jamie",
- role: "Happy Customer",
- avatarSrc: daBoiAvatar,
- socialUrl: "#",
- quote: "My cats love it!",
+ },
+ {
+ name: "Billy Howell",
+ role: "Entrepreneur",
+ avatarSrc:
+ "https://pbs.twimg.com/profile_images/1877734205561430016/jjpG4mS6_400x400.jpg",
+ socialUrl: "https://twitter.com/billyjhowell",
+ quote:
+ "Congrats! I am loving Wasp & Open SaaS. It's really helped me, a self-taught coder increase my confidence. I feel like I've finally found the perfect, versatile stack for all my projects instead of trying out a new one each time.",
},
+ },
+ {
+ name: "Tim Skaggs",
+ role: "Founder @ Antler US",
Expand Down Expand Up @@ -249,7 +253,7 @@
+ "https://dev.to/wasp/our-web-framework-reached-9000-stars-on-github-9000-jij#comment-2dech",
+ quote:
+ "This is exactly the framework I've been dreaming of ever since I've been waiting to fully venture into the JS Backend Dev world. I believe Wasp will go above 50k stars this year. The documentation alone gives me the confidence that this is my permanent Nodejs framework and I'm staying with Wasp. Phenomenal work by the team... Please keep up your amazing spirits. Thank you",
+ },
},
];
-
export const faqs = [
Expand All @@ -261,14 +265,14 @@
+ question: "Why is this SaaS Template free and open-source?",
+ answer:
+ "We believe the best product is made when the community puts their heads together. We also believe a quality starting point for a web app should be free and available to everyone. Our hope is that together we can create the best SaaS template out there and bring our ideas to customers quickly.",
},
+ },
+ {
+ id: 2,
+ question: "What's Wasp?",
+ href: "https://wasp-lang.dev",
+ answer:
+ "It's the fastest way to develop full-stack React + NodeJS + Prisma apps and it's what gives this template superpowers. Wasp relies on React, NodeJS, and Prisma to define web components and server queries and actions. Wasp's secret sauce is its compiler which takes the client, server code, and config file and outputs the client app, server app and deployment code, supercharging the development experience. Combined with this template, you can build a SaaS app in record time.",
+ },
},
];
-
export const footerNavigation = {
Expand Down
4 changes: 2 additions & 2 deletions opensaas-sh/app_diff/src/payment/paymentProcessor.ts.diff
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
--- template/app/src/payment/paymentProcessor.ts
+++ opensaas-sh/app/src/payment/paymentProcessor.ts
@@ -27,9 +27,4 @@
@@ -28,9 +28,4 @@
webhookMiddlewareConfigFn: MiddlewareConfigFn;
}

-/**
- * Choose which payment processor you'd like to use, then delete the
- * other payment processor code that you're not using from `/src/payment`
- */
-// export const paymentProcessor: PaymentProcessor = lemonSqueezyPaymentProcessor;
export const paymentProcessor: PaymentProcessor = stripePaymentProcessor;
-// export const paymentProcessor: PaymentProcessor = lemonSqueezyPaymentProcessor;
15 changes: 0 additions & 15 deletions opensaas-sh/app_diff/src/payment/stripe/paymentDetails.ts.diff

This file was deleted.

49 changes: 43 additions & 6 deletions opensaas-sh/app_diff/src/payment/stripe/paymentProcessor.ts.diff
Original file line number Diff line number Diff line change
@@ -1,11 +1,48 @@
--- template/app/src/payment/stripe/paymentProcessor.ts
+++ opensaas-sh/app/src/payment/stripe/paymentProcessor.ts
@@ -32,7 +32,7 @@
id: userId,
},
data: {
@@ -13,8 +13,8 @@
} from "./checkoutUtils";
import { stripeClient } from "./stripeClient";
import {
- fetchUserPaymentProcessorUserId,
- updateUserPaymentProcessorUserId,
+ fetchUserStripeId,
+ updateUserStripeId
} from "./user";
import { stripeMiddlewareConfigFn, stripeWebhook } from "./webhook";

@@ -28,10 +28,10 @@
}: CreateCheckoutSessionArgs) => {
const customer = await ensureStripeCustomer(userEmail);

- await updateUserPaymentProcessorUserId(
+ await updateUserStripeId(
{
userId,
- paymentProcessorUserId: customer.id,
+ stripeId: customer.id,
},
});
if (!stripeSession.url)
prismaUserDelegate,
);
@@ -59,18 +59,18 @@
prismaUserDelegate,
userId,
}: FetchCustomerPortalUrlArgs) => {
- const paymentProcessorUserId = await fetchUserPaymentProcessorUserId(
+ const stripeId = await fetchUserStripeId(
userId,
prismaUserDelegate,
);

- if (!paymentProcessorUserId) {
+ if (!stripeId) {
return null;
}

const billingPortalSession =
await stripeClient.billingPortal.sessions.create({
- customer: paymentProcessorUserId,
+ customer: stripeId,
return_url: `${config.frontendUrl}/account`,
});

65 changes: 65 additions & 0 deletions opensaas-sh/app_diff/src/payment/stripe/user.ts.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
--- template/app/src/payment/stripe/user.ts
+++ opensaas-sh/app/src/payment/stripe/user.ts
@@ -3,7 +3,7 @@
import type { SubscriptionStatus } from "../plans";
import { PaymentPlanId } from "../plans";

-export async function fetchUserPaymentProcessorUserId(
+export async function fetchUserStripeId(
userId: User["id"],
prismaUserDelegate: PrismaClient["user"],
): Promise<string | null> {
@@ -12,20 +12,20 @@
id: userId,
},
select: {
- paymentProcessorUserId: true,
+ stripeId: true,
},
});

- return user.paymentProcessorUserId;
+ return user.stripeId;
}

-interface UpdateUserPaymentProcessorUserIdArgs {
+interface UpdateUserStripeIdArgs {
userId: User["id"];
- paymentProcessorUserId: NonNullable<User["paymentProcessorUserId"]>;
+ stripeId: NonNullable<User["stripeId"]>;
}

-export function updateUserPaymentProcessorUserId(
- { userId, paymentProcessorUserId }: UpdateUserPaymentProcessorUserIdArgs,
+export function updateUserStripeId(
+ { userId, stripeId }: UpdateUserStripeIdArgs,
prismaUserDelegate: PrismaClient["user"],
): Promise<User> {
return prismaUserDelegate.update({
@@ -33,7 +33,7 @@
id: userId,
},
data: {
- paymentProcessorUserId,
+ stripeId
},
});
}
@@ -54,7 +54,7 @@
): Promise<User> {
return userDelegate.update({
where: {
- paymentProcessorUserId: customerId,
+ stripeId: customerId,
},
data: {
datePaid,
@@ -81,7 +81,7 @@
): Promise<User> {
return userDelegate.update({
where: {
- paymentProcessorUserId: customerId,
+ stripeId: customerId,
},
data: {
subscriptionPlan: paymentPlanId,
2 changes: 1 addition & 1 deletion opensaas-sh/blog/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# OpenSaaS Docs and Blog
# Open SaaS Docs and Blog

This is the docs and blog for the [OpenSaaS.sh](https://opensaas.sh/) website, [![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build)

Expand Down
2 changes: 1 addition & 1 deletion opensaas-sh/blog/src/content/docs/guides/deploying.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export const stripe = new Stripe(process.env.STRIPE_KEY!, {
2. click on `+ add endpoint`
3. enter your endpoint url, which will be the url of your deployed server + `/payments-webhook`, e.g. `https://open-saas-wasp-sh-server.fly.dev/payments-webhook`
<Image src={stripeListenEvents} alt="listen events" loading="lazy" />
4. select the events you want to listen to. These should be the same events you're consuming in your webhook which you can find listed in [`src/payment/stripe/webhookPayload.ts`](https://github.com/wasp-lang/open-saas/blob/main/template/app/src/payment/stripe/webhookPayload.ts):
4. select the events you want to listen to. These should be the same events you're consuming in your webhook which are handled in [`src/payment/stripe/webhook.ts`](https://github.com/wasp-lang/open-saas/blob/main/template/app/src/payment/stripe/webhook.ts):
<Image src={stripeSigningSecret} alt="signing secret" loading="lazy" />
5. after that, go to the webhook you just created and `reveal` the new signing secret.
6. add this secret to your deployed server's `STRIPE_WEBHOOK_SECRET=` environment variable. <br/>If you've deployed to Fly.io, you can do that easily with the following command:
Expand Down
Loading