- {testimonials.slice(0, itemsToShow).map((testimonial, idx) => (
+ {testimonials.map((testimonial, idx) => (
-
+-
- setIsExpanded(!isExpanded)}
-- className='px-6 py-3 text-sm font-medium text-primary bg-primary/10 hover:bg-primary/20 rounded-lg transition-colors duration-200'
+- className="text-primary bg-primary/10 hover:bg-primary/20 rounded-lg px-6 py-3 text-sm font-medium transition-colors duration-200"
- >
-- {isExpanded ? 'Show Less' : `Show ${testimonials.length - mobileItemsToShow} More`}
+- {isExpanded
+- ? "Show Less"
+- : `Show ${testimonials.length - mobileItemsToShow} More`}
-
-
- )}
diff --git a/opensaas-sh/app_diff/src/landing-page/contentSections.tsx.diff b/opensaas-sh/app_diff/src/landing-page/contentSections.tsx.diff
index 4edd9607..749a3635 100644
--- a/opensaas-sh/app_diff/src/landing-page/contentSections.tsx.diff
+++ b/opensaas-sh/app_diff/src/landing-page/contentSections.tsx.diff
@@ -1,176 +1,195 @@
--- template/app/src/landing-page/contentSections.tsx
+++ opensaas-sh/app/src/landing-page/contentSections.tsx
-@@ -0,0 +1,244 @@
-+import { routes } from 'wasp/client/router';
-+import type { NavigationItem } from '../client/components/NavBar/NavBar';
-+import blog from '../client/static/assets/blog.webp';
-+import email from '../client/static/assets/email.webp';
-+import fileupload from '../client/static/assets/fileupload.webp';
-+import ai from '../client/static/assets/openapi.webp';
-+import kivo from '../client/static/examples/kivo.webp';
-+import messync from '../client/static/examples/messync.webp';
-+import microinfluencerClub from '../client/static/examples/microinfluencers.webp';
-+import promptpanda from '../client/static/examples/promptpanda.webp';
-+import reviewradar from '../client/static/examples/reviewradar.webp';
-+import scribeist from '../client/static/examples/scribeist.webp';
-+import searchcraft from '../client/static/examples/searchcraft.webp';
-+import logo from '../client/static/logo.webp';
-+import { BlogUrl, DocsUrl, GithubUrl, WaspUrl } from '../shared/common';
-+import { GridFeature } from './components/FeaturesGrid';
+@@ -0,0 +1,263 @@
++import { routes } from "wasp/client/router";
++import type { NavigationItem } from "../client/components/NavBar/NavBar";
++import blog from "../client/static/assets/blog.webp";
++import email from "../client/static/assets/email.webp";
++import fileupload from "../client/static/assets/fileupload.webp";
++import ai from "../client/static/assets/openapi.webp";
++import kivo from "../client/static/examples/kivo.webp";
++import messync from "../client/static/examples/messync.webp";
++import microinfluencerClub from "../client/static/examples/microinfluencers.webp";
++import promptpanda from "../client/static/examples/promptpanda.webp";
++import reviewradar from "../client/static/examples/reviewradar.webp";
++import scribeist from "../client/static/examples/scribeist.webp";
++import searchcraft from "../client/static/examples/searchcraft.webp";
++import logo from "../client/static/logo.webp";
++import { BlogUrl, DocsUrl, GithubUrl, WaspUrl } from "../shared/common";
++import { GridFeature } from "./components/FeaturesGrid";
+
+export const landingPageNavigationItems: NavigationItem[] = [
-+ { name: 'Features', to: '#features' },
-+ { name: 'Documentation', to: DocsUrl },
-+ { name: 'Blog', to: BlogUrl },
++ { name: "Features", to: "#features" },
++ { name: "Documentation", to: DocsUrl },
++ { name: "Blog", to: BlogUrl },
+];
+export const features: GridFeature[] = [
+ {
-+ description: 'Have a sweet AI-powered app concept? Get your idea shipped to potential customers in days!',
-+ icon:
,
-+ href: DocsUrl,
-+ size: 'medium',
-+ fullWidthIcon: true,
-+ align: 'left',
-+ },
-+ {
-+ name: 'Full-stack Type Safety',
+ description:
-+ 'Full support for TypeScript with auto-generated types that span the whole stack. Nothing to configure!',
-+ emoji: '🥞',
++ "Have a sweet AI-powered app concept? Get your idea shipped to potential customers in days!",
++ icon:
,
+ href: DocsUrl,
-+ size: 'medium',
-+ },
-+ {
-+ description: 'File upload examples with AWS S3 presigned URLs are included and fully documented!',
-+ icon:
,
-+ href: DocsUrl + '/guides/file-uploading/',
-+ size: 'medium',
++ size: "medium",
+ fullWidthIcon: true,
++ align: "left",
+ },
+ {
-+ name: 'Email Sending',
++ name: "Full-stack Type Safety",
+ description:
-+ 'Email sending built-in. Combine it with the cron jobs feature to easily send emails to your customers.',
-+ icon:
,
-+ href: DocsUrl + '/guides/email-sending/',
-+ size: 'medium',
-+ fullWidthIcon: true,
-+ direction: 'col-reverse',
++ "Full support for TypeScript with auto-generated types that span the whole stack. Nothing to configure!",
++ emoji: "🥞",
++ href: DocsUrl,
++ size: "medium",
+ },
+ {
-+ name: 'Open SaaS',
-+ description: 'Try the demo app',
-+ icon:
,
++ description:
++ "File upload examples with AWS S3 presigned URLs are included and fully documented!",
++ icon: (
++
++ ),
++ href: DocsUrl + "/guides/file-uploading/",
++ size: "medium",
++ fullWidthIcon: true,
++ },
++ {
++ name: "Email Sending",
++ description:
++ "Email sending built-in. Combine it with the cron jobs feature to easily send emails to your customers.",
++ icon:
,
++ href: DocsUrl + "/guides/email-sending/",
++ size: "medium",
++ fullWidthIcon: true,
++ direction: "col-reverse",
++ },
++ {
++ name: "Open SaaS",
++ description: "Try the demo app",
++ icon:
,
+ href: routes.LoginRoute.to,
-+ size: 'medium',
++ size: "medium",
+ highlight: true,
+ },
+ {
-+ name: 'Blog w/ Astro',
++ name: "Blog w/ Astro",
+ description:
-+ 'Built-in blog with the Astro framework. Write your posts in Markdown, and watch your SEO performance take off.',
-+ icon:
,
-+ href: DocsUrl + '/start/guided-tour/',
-+ size: 'medium',
++ "Built-in blog with the Astro framework. Write your posts in Markdown, and watch your SEO performance take off.",
++ icon:
,
++ href: DocsUrl + "/start/guided-tour/",
++ size: "medium",
+ fullWidthIcon: true,
+ },
+ {
-+ name: 'Deploy Anywhere. Easily.',
++ name: "Deploy Anywhere. Easily.",
+ description:
-+ 'No vendor lock-in because you own all your code. Deploy yourself, or let Wasp deploy it for you with a single command.',
-+ emoji: '🚀',
-+ href: DocsUrl + '/guides/deploying/',
-+ size: 'medium',
++ "No vendor lock-in because you own all your code. Deploy yourself, or let Wasp deploy it for you with a single command.",
++ emoji: "🚀",
++ href: DocsUrl + "/guides/deploying/",
++ size: "medium",
+ },
+ {
-+ name: 'Complete Documentation & Support',
-+ description: 'And a Discord community to help!',
++ name: "Complete Documentation & Support",
++ description: "And a Discord community to help!",
+ href: DocsUrl,
-+ size: 'small',
++ size: "small",
+ },
+ {
-+ name: 'E2E Tests w/ Playwright',
-+ description: 'Tests and a CI pipeline w/ GitHub Actions',
-+ href: DocsUrl + '/guides/tests/',
-+ size: 'small',
++ name: "E2E Tests w/ Playwright",
++ description: "Tests and a CI pipeline w/ GitHub Actions",
++ href: DocsUrl + "/guides/tests/",
++ size: "small",
+ },
+ {
-+ name: 'Open-Source Philosophy',
++ name: "Open-Source Philosophy",
+ description:
-+ 'The repo and framework are 100% open-source, and so are the services wherever possible. Still missing something? Contribute!',
-+ emoji: '🤝',
++ "The repo and framework are 100% open-source, and so are the services wherever possible. Still missing something? Contribute!",
++ emoji: "🤝",
+ href: DocsUrl,
-+ size: 'medium',
++ size: "medium",
+ },
+];
+export const testimonials = [
+ {
-+ 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',
++ 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!',
++ "I used Wasp to build and sell my AI-augmented SaaS app for marketplace vendors within two months!",
+ },
+ {
-+ name: 'Jonathan Cocharan',
-+ role: 'Entrepreneur',
-+ avatarSrc: 'https://pbs.twimg.com/profile_images/1950172296376639488/sZ0JIqfR_400x400.jpg',
-+ socialUrl: 'https://twitter.com/JonathanCochran',
++ 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 🤯!',
++ "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: 'Billy Howell',
-+ role: 'Entrepreneur',
-+ avatarSrc: 'https://pbs.twimg.com/profile_images/1877734205561430016/jjpG4mS6_400x400.jpg',
-+ socialUrl: 'https://twitter.com/billyjhowell',
++ 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. 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',
-+ avatarSrc: 'https://pbs.twimg.com/profile_images/1802196804236091392/ZG0OE_fO_400x400.jpg',
-+ socialUrl: 'https://twitter.com/tskaggs',
-+ quote: 'Nearly done with a MVP in 3 days of part-time work... and deployed on Fly.io in 10 minutes.',
-+ },
-+ {
-+ name: 'Cam Blackwood',
-+ role: 'Founder @ Microinfluencer.club',
-+ avatarSrc: 'https://pbs.twimg.com/profile_images/1927721707164377089/it8oCAkf_400x400.jpg',
-+ socialUrl: 'https://twitter.com/CamBlackwood95',
-+ quote: 'Setting up a full stack SaaS in 1 minute with WaspLang.',
-+ },
-+ {
-+ name: 'JLegendz',
-+ role: 'Enterpreneur',
++ name: "Tim Skaggs",
++ role: "Founder @ Antler US",
+ avatarSrc:
-+ 'https://cdn.discordapp.com/avatars/1003468772251811921/a_c6124fcbee5621d1ad9cca83a102c4a9.png?size=80',
-+ socialUrl: 'https://discord.com/channels/686873244791210014/1080864617347162122/1246388561020850188',
++ "https://pbs.twimg.com/profile_images/1802196804236091392/ZG0OE_fO_400x400.jpg",
++ socialUrl: "https://twitter.com/tskaggs",
++ quote:
++ "Nearly done with a MVP in 3 days of part-time work... and deployed on Fly.io in 10 minutes.",
++ },
++ {
++ name: "Cam Blackwood",
++ role: "Founder @ Microinfluencer.club",
++ avatarSrc:
++ "https://pbs.twimg.com/profile_images/1927721707164377089/it8oCAkf_400x400.jpg",
++ socialUrl: "https://twitter.com/CamBlackwood95",
++ quote: "Setting up a full stack SaaS in 1 minute with WaspLang.",
++ },
++ {
++ name: "JLegendz",
++ role: "Enterpreneur",
++ avatarSrc:
++ "https://cdn.discordapp.com/avatars/1003468772251811921/a_c6124fcbee5621d1ad9cca83a102c4a9.png?size=80",
++ socialUrl:
++ "https://discord.com/channels/686873244791210014/1080864617347162122/1246388561020850188",
+ quote:
+ "Just randomly wanted to say that I've been loving working with Wasp so far. The open-saas template is great starting point and great way to learn how Wasp works. The documentation is superb and I see the GitHub is super active. The team is super responsive and the ai kapa rocks! So thanks for the work you all are doing. I’ve done plenty of with react in the past but I’m a front end person. With wasp though, I'm managing my db, back end functions, actions, queries, all with so much ease. I occasionally get stuck on an issue but within a day or two, and thanks to a couple of AI assistants, I get through it. So thank you!",
+ },
+ {
-+ name: 'Dimitrios Mastrogiannis',
-+ role: 'Founder @ Kivo.dev',
-+ avatarSrc: 'https://pbs.twimg.com/profile_images/1771240035020324864/bcNSr-dA_400x400.jpg',
-+ socialUrl: 'https://twitter.com/dmastroyiannis',
++ name: "Dimitrios Mastrogiannis",
++ role: "Founder @ Kivo.dev",
++ avatarSrc:
++ "https://pbs.twimg.com/profile_images/1771240035020324864/bcNSr-dA_400x400.jpg",
++ socialUrl: "https://twitter.com/dmastroyiannis",
+ quote: "Without Wasp & Open SaaS, Kivo.dev wouldn't exist",
+ },
+ {
-+ name: 'Alex Ionascu',
-+ role: 'Entrepreneur',
-+ avatarSrc: 'https://pbs.twimg.com/profile_images/1356710335001018376/HEfgRu8X_400x400.jpg',
-+ socialUrl: 'https://twitter.com/alexandrionascu',
-+ quote: "Wasp is like hot water. You don't realise how much you need it unless you try it.",
++ name: "Alex Ionascu",
++ role: "Entrepreneur",
++ avatarSrc:
++ "https://pbs.twimg.com/profile_images/1356710335001018376/HEfgRu8X_400x400.jpg",
++ socialUrl: "https://twitter.com/alexandrionascu",
++ quote:
++ "Wasp is like hot water. You don't realise how much you need it unless you try it.",
+ },
+ {
-+ name: 'Emm Ajayi',
-+ role: 'Enterpreneur',
++ name: "Emm Ajayi",
++ role: "Enterpreneur",
+ avatarSrc:
-+ 'https://media2.dev.to/dynamic/image/width=320,height=320,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1215082%2F860c57b3-ac41-420b-9420-b6efda743596.jpg',
-+ socialUrl: 'https://dev.to/wasp/our-web-framework-reached-9000-stars-on-github-9000-jij#comment-2dech',
++ "https://media2.dev.to/dynamic/image/width=320,height=320,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1215082%2F860c57b3-ac41-420b-9420-b6efda743596.jpg",
++ socialUrl:
++ "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",
+ },
@@ -178,70 +197,70 @@
+export const faqs = [
+ {
+ id: 1,
-+ question: 'Why is this SaaS Template free and open-source?',
++ 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.',
++ "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',
++ 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 = {
+ app: [
-+ { name: 'Github', href: GithubUrl },
-+ { name: 'Documentation', href: DocsUrl },
-+ { name: 'Blog', href: BlogUrl },
++ { name: "Github", href: GithubUrl },
++ { name: "Documentation", href: DocsUrl },
++ { name: "Blog", href: BlogUrl },
+ ],
+ company: [
-+ { name: 'Terms of Service', href: GithubUrl + '/blob/main/LICENSE' },
-+ { name: 'Made by the Wasp team = }', href: WaspUrl },
++ { name: "Terms of Service", href: GithubUrl + "/blob/main/LICENSE" },
++ { name: "Made by the Wasp team = }", href: WaspUrl },
+ ],
+};
+export const examples = [
+ {
-+ name: 'Microinfluencers',
-+ description: 'microinfluencer.club',
++ name: "Microinfluencers",
++ description: "microinfluencer.club",
+ imageSrc: microinfluencerClub,
-+ href: 'https://microinfluencer.club',
++ href: "https://microinfluencer.club",
+ },
+ {
-+ name: 'Kivo',
-+ description: 'kivo.dev',
++ name: "Kivo",
++ description: "kivo.dev",
+ imageSrc: kivo,
-+ href: 'https://kivo.dev',
++ href: "https://kivo.dev",
+ },
+ {
-+ name: 'Searchcraft',
-+ description: 'searchcraft.io',
++ name: "Searchcraft",
++ description: "searchcraft.io",
+ imageSrc: searchcraft,
-+ href: 'https://www.searchcraft.io',
++ href: "https://www.searchcraft.io",
+ },
+ {
-+ name: 'Scribeist',
-+ description: 'scribeist.com',
++ name: "Scribeist",
++ description: "scribeist.com",
+ imageSrc: scribeist,
-+ href: 'https://scribeist.com',
++ href: "https://scribeist.com",
+ },
+ {
-+ name: 'Messync',
-+ description: 'messync.com',
++ name: "Messync",
++ description: "messync.com",
+ imageSrc: messync,
-+ href: 'https://messync.com',
++ href: "https://messync.com",
+ },
+ {
-+ name: 'Prompt Panda',
-+ description: 'promptpanda.io',
++ name: "Prompt Panda",
++ description: "promptpanda.io",
+ imageSrc: promptpanda,
-+ href: 'https://promptpanda.io',
++ href: "https://promptpanda.io",
+ },
+ {
-+ name: 'Review Radar',
-+ description: 'reviewradar.ai',
++ name: "Review Radar",
++ description: "reviewradar.ai",
+ imageSrc: reviewradar,
-+ href: 'https://reviewradar.ai',
++ href: "https://reviewradar.ai",
+ },
+];
diff --git a/opensaas-sh/app_diff/src/landing-page/logos/PrismaLogo.tsx.diff b/opensaas-sh/app_diff/src/landing-page/logos/PrismaLogo.tsx.diff
index cf428bd8..dbd4133b 100644
--- a/opensaas-sh/app_diff/src/landing-page/logos/PrismaLogo.tsx.diff
+++ b/opensaas-sh/app_diff/src/landing-page/logos/PrismaLogo.tsx.diff
@@ -1,16 +1,13 @@
--- template/app/src/landing-page/logos/PrismaLogo.tsx
+++ opensaas-sh/app/src/landing-page/logos/PrismaLogo.tsx
-@@ -1,11 +1,11 @@
+@@ -1,8 +1,8 @@
export default function PrismaLogo() {
return (
--
-+
-
-
-- )
-+ );
- }
+
diff --git a/opensaas-sh/app_diff/src/landing-page/logos/ReactLogo.tsx.diff b/opensaas-sh/app_diff/src/landing-page/logos/ReactLogo.tsx.diff
index f9e62070..aa1cc600 100644
--- a/opensaas-sh/app_diff/src/landing-page/logos/ReactLogo.tsx.diff
+++ b/opensaas-sh/app_diff/src/landing-page/logos/ReactLogo.tsx.diff
@@ -1,14 +1,30 @@
--- template/app/src/landing-page/logos/ReactLogo.tsx
+++ opensaas-sh/app/src/landing-page/logos/ReactLogo.tsx
-@@ -0,0 +1,12 @@
+@@ -0,0 +1,28 @@
+export default function ReactLogo() {
+ return (
-+
-+
-+
-+
-+
-+
++
++
++
++
++
++
+
+
+ );
diff --git a/opensaas-sh/app_diff/src/landing-page/logos/SalesforceLogo.tsx.diff b/opensaas-sh/app_diff/src/landing-page/logos/SalesforceLogo.tsx.diff
index 9bbc9bf6..b116ac94 100644
--- a/opensaas-sh/app_diff/src/landing-page/logos/SalesforceLogo.tsx.diff
+++ b/opensaas-sh/app_diff/src/landing-page/logos/SalesforceLogo.tsx.diff
@@ -1,46 +1,51 @@
--- template/app/src/landing-page/logos/SalesforceLogo.tsx
+++ opensaas-sh/app/src/landing-page/logos/SalesforceLogo.tsx
-@@ -1,27 +1,18 @@
+@@ -1,27 +1,24 @@
-export default function SalesforceLogo() {
-+import React from 'react';
++import React from "react";
+
+const SalesforceLogo: React.FC = () => {
return (
--
+-
-
--
+-
-
--
+-
-
-
-
-
-+
++
+
+
-- )
+ );
-}
-+ );
+};
+
+export default SalesforceLogo;
diff --git a/opensaas-sh/app_diff/src/landing-page/logos/ShadCNLogo.tsx.diff b/opensaas-sh/app_diff/src/landing-page/logos/ShadCNLogo.tsx.diff
index 16f3a425..087bb67d 100644
--- a/opensaas-sh/app_diff/src/landing-page/logos/ShadCNLogo.tsx.diff
+++ b/opensaas-sh/app_diff/src/landing-page/logos/ShadCNLogo.tsx.diff
@@ -1,31 +1,36 @@
--- template/app/src/landing-page/logos/ShadCNLogo.tsx
+++ opensaas-sh/app/src/landing-page/logos/ShadCNLogo.tsx
-@@ -0,0 +1,29 @@
+@@ -0,0 +1,34 @@
+export default function ShadCNLogo() {
+ return (
-+
-+
++
++
+
+
+
+ );
diff --git a/opensaas-sh/app_diff/src/lib/utils.ts.diff b/opensaas-sh/app_diff/src/lib/utils.ts.diff
index a65db331..52d923a5 100644
--- a/opensaas-sh/app_diff/src/lib/utils.ts.diff
+++ b/opensaas-sh/app_diff/src/lib/utils.ts.diff
@@ -7,9 +7,9 @@
+
+export function formatNumber(number: number) {
+ if (number >= 1_000_000) {
-+ return (number / 1_000_000).toFixed(1) + 'M';
++ return (number / 1_000_000).toFixed(1) + "M";
+ }
+ if (number >= 1_000) {
-+ return (number / 1_000).toFixed(1) + 'K';
++ return (number / 1_000).toFixed(1) + "K";
+ }
+}
diff --git a/opensaas-sh/app_diff/src/payment/PricingPage.tsx.diff b/opensaas-sh/app_diff/src/payment/PricingPage.tsx.diff
index 8d8b32b1..208d8d19 100644
--- a/opensaas-sh/app_diff/src/payment/PricingPage.tsx.diff
+++ b/opensaas-sh/app_diff/src/payment/PricingPage.tsx.diff
@@ -1,29 +1,30 @@
--- template/app/src/payment/PricingPage.tsx
+++ opensaas-sh/app/src/payment/PricingPage.tsx
-@@ -10,6 +10,7 @@
- import { PaymentPlanId, paymentPlans, prettyPaymentPlanName, SubscriptionStatus } from './plans';
+@@ -24,6 +24,7 @@
+ } from "./plans";
const bestDealPaymentPlanId: PaymentPlanId = PaymentPlanId.Pro;
-+const PaymentsDocsURL = 'https://docs.opensaas.sh/guides/payments-integration/';
++const PaymentsDocsURL = "https://docs.opensaas.sh/guides/payments-integration/";
interface PaymentPlanCard {
name: string;
-@@ -109,8 +110,16 @@
+@@ -125,9 +126,16 @@
-- Choose between Stripe and LemonSqueezy as your payment provider. Just add your Product IDs! Try it
-- out below with test credit card number
-+ Choose between{' '}
-+
+
+- Choose between Stripe and LemonSqueezy as your payment provider. Just
+- add your Product IDs! Try it out below with test credit card number{" "}
+-
++ Choose between{" "}
++
+ Stripe
-+ {' '}
-+ and{' '}
-+
++ {" "}
++ and{" "}
++
+ LemonSqueezy
-+ {' '}
-+ as your payment provider. Just add your Product IDs! Try it out below with test credit card number{' '}
-+
-
++
{" "}
++ as your payment provider. Just add your Product IDs! Try it out below
++ with test credit card number
+
4242 4242 4242 4242 4242
diff --git a/opensaas-sh/app_diff/src/payment/paymentProcessor.ts.diff b/opensaas-sh/app_diff/src/payment/paymentProcessor.ts.diff
index c151459d..979d0136 100644
--- a/opensaas-sh/app_diff/src/payment/paymentProcessor.ts.diff
+++ b/opensaas-sh/app_diff/src/payment/paymentProcessor.ts.diff
@@ -1,19 +1,11 @@
--- template/app/src/payment/paymentProcessor.ts
+++ opensaas-sh/app/src/payment/paymentProcessor.ts
-@@ -3,7 +3,6 @@
- import type { MiddlewareConfigFn } from 'wasp/server';
- import { PrismaClient } from '@prisma/client';
- import { stripePaymentProcessor } from './stripe/paymentProcessor';
--import { lemonSqueezyPaymentProcessor } from './lemonSqueezy/paymentProcessor';
-
- export interface CreateCheckoutSessionArgs {
- userId: string;
-@@ -24,9 +23,4 @@
+@@ -27,9 +27,4 @@
webhookMiddlewareConfigFn: MiddlewareConfigFn;
}
-/**
-- * Choose which payment processor you'd like to use, then delete the
+- * 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;
diff --git a/opensaas-sh/app_diff/src/payment/stripe/paymentDetails.ts.diff b/opensaas-sh/app_diff/src/payment/stripe/paymentDetails.ts.diff
index b87e266d..b9dd1586 100644
--- a/opensaas-sh/app_diff/src/payment/stripe/paymentDetails.ts.diff
+++ b/opensaas-sh/app_diff/src/payment/stripe/paymentDetails.ts.diff
@@ -1,11 +1,11 @@
--- template/app/src/payment/stripe/paymentDetails.ts
+++ opensaas-sh/app/src/payment/stripe/paymentDetails.ts
-@@ -14,10 +14,10 @@
+@@ -20,10 +20,10 @@
) => {
return userDelegate.update({
where: {
-- paymentProcessorUserId: userStripeId
-+ stripeId: userStripeId
+- paymentProcessorUserId: userStripeId,
++ stripeId: userStripeId,
},
data: {
- paymentProcessorUserId: userStripeId,
diff --git a/opensaas-sh/app_diff/src/payment/stripe/paymentProcessor.ts.diff b/opensaas-sh/app_diff/src/payment/stripe/paymentProcessor.ts.diff
index c5443612..bd3d9ae4 100644
--- a/opensaas-sh/app_diff/src/payment/stripe/paymentProcessor.ts.diff
+++ b/opensaas-sh/app_diff/src/payment/stripe/paymentProcessor.ts.diff
@@ -1,11 +1,11 @@
--- template/app/src/payment/stripe/paymentProcessor.ts
+++ opensaas-sh/app/src/payment/stripe/paymentProcessor.ts
-@@ -20,7 +20,7 @@
- id: userId
+@@ -32,7 +32,7 @@
+ id: userId,
},
data: {
-- paymentProcessorUserId: customer.id
-+ stripeId: customer.id
- }
- })
- if (!stripeSession.url) throw new Error('Error creating Stripe Checkout Session');
+- paymentProcessorUserId: customer.id,
++ stripeId: customer.id,
+ },
+ });
+ if (!stripeSession.url)
diff --git a/opensaas-sh/app_diff/src/server/scripts/dbSeeds.ts.diff b/opensaas-sh/app_diff/src/server/scripts/dbSeeds.ts.diff
index c89c6db6..5d24aaec 100644
--- a/opensaas-sh/app_diff/src/server/scripts/dbSeeds.ts.diff
+++ b/opensaas-sh/app_diff/src/server/scripts/dbSeeds.ts.diff
@@ -1,14 +1,20 @@
--- template/app/src/server/scripts/dbSeeds.ts
+++ opensaas-sh/app/src/server/scripts/dbSeeds.ts
-@@ -37,9 +37,11 @@
+@@ -45,15 +45,15 @@
isAdmin: false,
credits,
subscriptionStatus,
- lemonSqueezyCustomerPortalUrl: null,
-- paymentProcessorUserId: hasUserPaidOnStripe ? `cus_test_${faker.string.uuid()}` : null,
+- paymentProcessorUserId: hasUserPaidOnStripe
+- ? `cus_test_${faker.string.uuid()}`
+- : null,
+ stripeId: hasUserPaidOnStripe ? `cus_test_${faker.string.uuid()}` : null,
- datePaid: hasUserPaidOnStripe ? faker.date.between({ from: createdAt, to: timePaid }) : null,
- subscriptionPlan: subscriptionStatus ? faker.helpers.arrayElement(getSubscriptionPaymentPlanIds()) : null,
+ datePaid: hasUserPaidOnStripe
+ ? faker.date.between({ from: createdAt, to: timePaid })
+ : null,
+ subscriptionPlan: subscriptionStatus
+ ? faker.helpers.arrayElement(getSubscriptionPaymentPlanIds())
+ : null,
+ // For the demo app, we want to default isMockUser to true so that our admin dash only shows mock users
+ // and not real users signing up to test the app
+ isMockUser: true,
diff --git a/opensaas-sh/app_diff/src/shared/common.ts.diff b/opensaas-sh/app_diff/src/shared/common.ts.diff
index 4f5fcb8d..fb8b06fc 100644
--- a/opensaas-sh/app_diff/src/shared/common.ts.diff
+++ b/opensaas-sh/app_diff/src/shared/common.ts.diff
@@ -1,7 +1,7 @@
--- template/app/src/shared/common.ts
+++ opensaas-sh/app/src/shared/common.ts
@@ -1,2 +1,4 @@
- export const DocsUrl = 'https://docs.opensaas.sh';
- export const BlogUrl = 'https://docs.opensaas.sh/blog';
-+export const GithubUrl = 'https://github.com/wasp-lang/open-saas';
-+export const WaspUrl = 'https://wasp.sh';
+ export const DocsUrl = "https://docs.opensaas.sh";
+ export const BlogUrl = "https://docs.opensaas.sh/blog";
++export const GithubUrl = "https://github.com/wasp-lang/open-saas";
++export const WaspUrl = "https://wasp.sh";
diff --git a/opensaas-sh/app_diff/src/user/operations.ts.diff b/opensaas-sh/app_diff/src/user/operations.ts.diff
index bccc675e..8279cb35 100644
--- a/opensaas-sh/app_diff/src/user/operations.ts.diff
+++ b/opensaas-sh/app_diff/src/user/operations.ts.diff
@@ -1,26 +1,28 @@
--- template/app/src/user/operations.ts
+++ opensaas-sh/app/src/user/operations.ts
-@@ -34,10 +34,7 @@
- };
-
+@@ -48,12 +48,7 @@
type GetPaginatedUsersOutput = {
-- users: Pick<
-- User,
-- 'id' | 'email' | 'username' | 'subscriptionStatus' | 'paymentProcessorUserId' | 'isAdmin'
-- >[];
-+ users: Pick[];
+ users: Pick<
+ User,
+- | "id"
+- | "email"
+- | "username"
+- | "subscriptionStatus"
+- | "paymentProcessorUserId"
+- | "isAdmin"
++ "id" | "email" | "username" | "subscriptionStatus" | "stripeId" | "isAdmin"
+ >[];
totalPages: number;
};
-
-@@ -85,6 +82,7 @@
- mode: 'insensitive',
+@@ -118,6 +113,7 @@
+ mode: "insensitive",
},
isAdmin,
+ isMockUser: true,
},
{
OR: [
-@@ -106,7 +104,7 @@
+@@ -139,7 +135,7 @@
username: true,
isAdmin: true,
subscriptionStatus: true,
@@ -28,4 +30,4 @@
+ stripeId: true,
},
orderBy: {
- username: 'asc',
+ username: "asc",
diff --git a/opensaas-sh/app_diff/tailwind.config.js.diff b/opensaas-sh/app_diff/tailwind.config.js.diff
index a65dce40..050b8fb9 100644
--- a/opensaas-sh/app_diff/tailwind.config.js.diff
+++ b/opensaas-sh/app_diff/tailwind.config.js.diff
@@ -1,13 +1,13 @@
--- template/app/tailwind.config.js
+++ opensaas-sh/app/tailwind.config.js
@@ -254,6 +254,10 @@
- 7: '-5px 0 0 #313D4A, 5px 0 0 #313D4A',
- 8: '1px 0 0 #313D4A, -1px 0 0 #313D4A, 0 1px 0 #313D4A, 0 -1px 0 #313D4A, 0 3px 13px rgb(0 0 0 / 8%)',
- default: '0px 8px 13px -3px rgba(0, 0, 0, 0.07)',
+ 7: "-5px 0 0 #313D4A, 5px 0 0 #313D4A",
+ 8: "1px 0 0 #313D4A, -1px 0 0 #313D4A, 0 1px 0 #313D4A, 0 -1px 0 #313D4A, 0 3px 13px rgb(0 0 0 / 8%)",
+ default: "0px 8px 13px -3px rgba(0, 0, 0, 0.07)",
+ outer:
-+ '0px 1px 3px 0px hsl(var(--background)/.8) inset, 0px 0.5px 1px 0px hsl(var(--background)/.8) inset, 0px -1px 3px 0px hsl(var(--primary)/.3) inset, 0px -0.5px 1px 0px hsl(var(--primary)/.15) inset, 0px -2px 4.8px 0px hsl(var(--background)/.05), 0px 1px 2px 0px hsl(var(--background)/.1), 0px 2px 4px 0px hsl(var(--background)/.1), 0px 4px 8px 0px hsl(var(--background)/.15);',
++ "0px 1px 3px 0px hsl(var(--background)/.8) inset, 0px 0.5px 1px 0px hsl(var(--background)/.8) inset, 0px -1px 3px 0px hsl(var(--primary)/.3) inset, 0px -0.5px 1px 0px hsl(var(--primary)/.15) inset, 0px -2px 4.8px 0px hsl(var(--background)/.05), 0px 1px 2px 0px hsl(var(--background)/.1), 0px 2px 4px 0px hsl(var(--background)/.1), 0px 4px 8px 0px hsl(var(--background)/.15);",
+ inner:
-+ '0px 1px 3px 0px hsl(var(--background)/.8), 0px 0.5px 1px 0px hsl(var(--background)/.5), 0px -1px 3px 0px hsl(var(--primary)/.5), 0px -0.5px 1px 0px hsl(var(--primary)/.5), 0px -1px 4px 0px hsl(var(--background)/.06) inset, 0px -2px 4.8px 0px hsl(var(--background)/.06) inset, 0px 1px 2px 0px hsl(var(--background)/.06) inset, 0px 2px 4px 0px hsl(var(--background)/.06) inset, 0px 4px 8px 0px hsl(var(--background)/.06) inset',
- card: '0px 1px 3px rgba(0, 0, 0, 0.12)',
- 'card-2': '0px 1px 2px rgba(0, 0, 0, 0.05)',
++ "0px 1px 3px 0px hsl(var(--background)/.8), 0px 0.5px 1px 0px hsl(var(--background)/.5), 0px -1px 3px 0px hsl(var(--primary)/.5), 0px -0.5px 1px 0px hsl(var(--primary)/.5), 0px -1px 4px 0px hsl(var(--background)/.06) inset, 0px -2px 4.8px 0px hsl(var(--background)/.06) inset, 0px 1px 2px 0px hsl(var(--background)/.06) inset, 0px 2px 4px 0px hsl(var(--background)/.06) inset, 0px 4px 8px 0px hsl(var(--background)/.06) inset",
+ card: "0px 1px 3px rgba(0, 0, 0, 0.12)",
+ "card-2": "0px 1px 2px rgba(0, 0, 0, 0.05)",
switcher: