From 0789c397eedd673ee3cac2dd24e14971090ed999 Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Sun, 21 Apr 2024 04:24:39 +0500 Subject: [PATCH 1/6] feat(saas): Landing page --- starterkits/saas/next.config.mjs | 4 +- .../(web)/_components/general-components.tsx | 27 ++++++- .../src/app/(web)/_components/header-auth.tsx | 5 +- starterkits/saas/src/app/(web)/blog/page.tsx | 6 +- starterkits/saas/src/app/(web)/page.tsx | 72 ++++++++++++++++++- .../saas/src/app/(web)/pricing/page.tsx | 6 +- .../saas/src/app/(web)/support/page.tsx | 9 +-- 7 files changed, 112 insertions(+), 17 deletions(-) diff --git a/starterkits/saas/next.config.mjs b/starterkits/saas/next.config.mjs index cc7fd27..211d6d1 100644 --- a/starterkits/saas/next.config.mjs +++ b/starterkits/saas/next.config.mjs @@ -11,7 +11,9 @@ const nextConfig = { experimental: { optimizePackageImports: ["lucide-react"], }, - images: { remotePatterns: [{ hostname: "fakeimg.pl" }] }, + images: { + remotePatterns: [{ hostname: "fakeimg.pl" }, { hostname: "utfs.io" }], + }, typescript: { ignoreBuildErrors: true, }, diff --git a/starterkits/saas/src/app/(web)/_components/general-components.tsx b/starterkits/saas/src/app/(web)/_components/general-components.tsx index 0d172cb..82cc63e 100644 --- a/starterkits/saas/src/app/(web)/_components/general-components.tsx +++ b/starterkits/saas/src/app/(web)/_components/general-components.tsx @@ -22,13 +22,36 @@ export function WebPageWrapper({ className, )} > + {children} ); } // This is a page heading used in all public web pages -export function WebPageHeading({ +export function WebPageHeader({ title, badge, children, @@ -46,7 +69,7 @@ export function WebPageHeading({ )} {title} diff --git a/starterkits/saas/src/app/(web)/_components/header-auth.tsx b/starterkits/saas/src/app/(web)/_components/header-auth.tsx index 6a85ad4..5463107 100644 --- a/starterkits/saas/src/app/(web)/_components/header-auth.tsx +++ b/starterkits/saas/src/app/(web)/_components/header-auth.tsx @@ -27,7 +27,10 @@ export async function HeaderAuth() { })} > Sign Up - — it's free + + {" "} + — it's free + )} diff --git a/starterkits/saas/src/app/(web)/blog/page.tsx b/starterkits/saas/src/app/(web)/blog/page.tsx index 431d1e7..a2c1469 100644 --- a/starterkits/saas/src/app/(web)/blog/page.tsx +++ b/starterkits/saas/src/app/(web)/blog/page.tsx @@ -1,5 +1,5 @@ import { - WebPageHeading, + WebPageHeader, WebPageWrapper, } from "@/app/(web)/_components/general-components"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; @@ -16,11 +16,11 @@ export default async function BlogsPage() { return ( - +

Get the latest news and updates

-
+ diff --git a/starterkits/saas/src/app/(web)/page.tsx b/starterkits/saas/src/app/(web)/page.tsx index c6a2cb3..edd15ba 100644 --- a/starterkits/saas/src/app/(web)/page.tsx +++ b/starterkits/saas/src/app/(web)/page.tsx @@ -1,3 +1,73 @@ +import { + WebPageHeader, + WebPageWrapper, +} from "@/app/(web)/_components/general-components"; +import { buttonVariants } from "@/components/ui/button"; +import { Icons } from "@/components/ui/icons"; +import { siteUrls } from "@/config/urls"; +import Image from "next/image"; +import Link from "next/link"; +import Balancer from "react-wrap-balancer"; + +export const dynamic = "force-static"; + export default async function HomePage() { - return
; + return ( + + + + Elevate your development game with Rapidlaunch! Launch your + apps faster with our SaaS starterkits, components, building + guides, and more. Customizable. Open Source. + + +
+ + Github + + + + Signup + + — it's free + + +
+
+ +
+
+ dashboard preview + + dashboard preview +
+
+
+ ); } diff --git a/starterkits/saas/src/app/(web)/pricing/page.tsx b/starterkits/saas/src/app/(web)/pricing/page.tsx index f6b1053..4d252aa 100644 --- a/starterkits/saas/src/app/(web)/pricing/page.tsx +++ b/starterkits/saas/src/app/(web)/pricing/page.tsx @@ -1,6 +1,6 @@ import { PricingTable } from "@/app/(web)/pricing/_components/pricing-table"; import { - WebPageHeading, + WebPageHeader, WebPageWrapper, } from "@/app/(web)/_components/general-components"; @@ -14,7 +14,7 @@ import { export default function PricingPage() { return ( - @@ -24,7 +24,7 @@ export default function PricingPage() { - Cancel at any time

-
+
diff --git a/starterkits/saas/src/app/(web)/support/page.tsx b/starterkits/saas/src/app/(web)/support/page.tsx index 6afc61f..b5f2c19 100644 --- a/starterkits/saas/src/app/(web)/support/page.tsx +++ b/starterkits/saas/src/app/(web)/support/page.tsx @@ -1,5 +1,5 @@ import { - WebPageHeading, + WebPageHeader, WebPageWrapper, } from "@/app/(web)/_components/general-components"; import { buttonVariants } from "@/components/ui/button"; @@ -16,15 +16,12 @@ import Link from "next/link"; export default function ContactPage() { return ( - +

If you have any questions or need help, feel free to reach out to us.

-
+
{supportInfos.map((supportInfo) => ( From 9cec7c6cf12a34c4fb8006666877e91b6357e307 Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Sun, 21 Apr 2024 15:43:05 +0500 Subject: [PATCH 2/6] feat(saas): added promotion section to landing page --- .../src/app/(web)/_components/background.tsx | 34 +++++++++++++++++++ .../(web)/_components/general-components.tsx | 23 ------------- .../src/app/(web)/_components/promotion.tsx | 20 +++++++++++ starterkits/saas/src/app/(web)/layout.tsx | 7 ++-- starterkits/saas/src/app/(web)/page.tsx | 3 ++ 5 files changed, 62 insertions(+), 25 deletions(-) create mode 100644 starterkits/saas/src/app/(web)/_components/background.tsx create mode 100644 starterkits/saas/src/app/(web)/_components/promotion.tsx diff --git a/starterkits/saas/src/app/(web)/_components/background.tsx b/starterkits/saas/src/app/(web)/_components/background.tsx new file mode 100644 index 0000000..7f83929 --- /dev/null +++ b/starterkits/saas/src/app/(web)/_components/background.tsx @@ -0,0 +1,34 @@ +type BackgroundProps = { + children: React.ReactNode; +}; + +export function Background({ children }: BackgroundProps) { + return ( + <> + + {children} + + ); +} diff --git a/starterkits/saas/src/app/(web)/_components/general-components.tsx b/starterkits/saas/src/app/(web)/_components/general-components.tsx index 82cc63e..9119b25 100644 --- a/starterkits/saas/src/app/(web)/_components/general-components.tsx +++ b/starterkits/saas/src/app/(web)/_components/general-components.tsx @@ -22,29 +22,6 @@ export function WebPageWrapper({ className, )} > - {children} ); diff --git a/starterkits/saas/src/app/(web)/_components/promotion.tsx b/starterkits/saas/src/app/(web)/_components/promotion.tsx new file mode 100644 index 0000000..d553060 --- /dev/null +++ b/starterkits/saas/src/app/(web)/_components/promotion.tsx @@ -0,0 +1,20 @@ +import Balancer from "react-wrap-balancer"; + +export function Promotion() { + return ( +
+ + Launch your SaaS in just a few days 🚀 + + + Because Rapidlaunch comes with a SaaS starter kit, Blocks and + guides, and more, you can launch your SaaS in just a few days. + Get started with our starter kits, components, building guides, + and more. Customizable.{" "} + + Open Source. + + +
+ ); +} diff --git a/starterkits/saas/src/app/(web)/layout.tsx b/starterkits/saas/src/app/(web)/layout.tsx index 5764924..edf171d 100644 --- a/starterkits/saas/src/app/(web)/layout.tsx +++ b/starterkits/saas/src/app/(web)/layout.tsx @@ -1,3 +1,4 @@ +import { Background } from "@/app/(web)/_components/background"; import { WebHeader } from "@/app/(web)/_components/header"; type WebLayoutProps = { @@ -7,8 +8,10 @@ type WebLayoutProps = { export default function WebLayout({ children }: WebLayoutProps) { return (
- - {children} + + + {children} +
); } diff --git a/starterkits/saas/src/app/(web)/page.tsx b/starterkits/saas/src/app/(web)/page.tsx index edd15ba..4b3a8e1 100644 --- a/starterkits/saas/src/app/(web)/page.tsx +++ b/starterkits/saas/src/app/(web)/page.tsx @@ -2,6 +2,7 @@ import { WebPageHeader, WebPageWrapper, } from "@/app/(web)/_components/general-components"; +import { Promotion } from "@/app/(web)/_components/promotion"; import { buttonVariants } from "@/components/ui/button"; import { Icons } from "@/components/ui/icons"; import { siteUrls } from "@/config/urls"; @@ -68,6 +69,8 @@ export default async function HomePage() { />
+ +
); } From d8896766366771d57df8b68b5758e35911218f15 Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Sun, 21 Apr 2024 16:36:56 +0500 Subject: [PATCH 3/6] feat(saas): Features section on landing page --- .../billing/_components/available-plans.tsx | 4 +- .../src/app/(web)/_components/background.tsx | 2 +- .../src/app/(web)/_components/features.tsx | 90 +++++++++++++++++++ starterkits/saas/src/app/(web)/page.tsx | 3 + .../pricing/_components/pricing-table.tsx | 8 +- starterkits/saas/src/config/features.ts | 60 +++++++++++++ starterkits/saas/src/config/pricing.ts | 4 +- 7 files changed, 164 insertions(+), 7 deletions(-) create mode 100644 starterkits/saas/src/app/(web)/_components/features.tsx create mode 100644 starterkits/saas/src/config/features.ts diff --git a/starterkits/saas/src/app/(app)/(user)/org/billing/_components/available-plans.tsx b/starterkits/saas/src/app/(app)/(user)/org/billing/_components/available-plans.tsx index d7b3682..e646f0d 100644 --- a/starterkits/saas/src/app/(app)/(user)/org/billing/_components/available-plans.tsx +++ b/starterkits/saas/src/app/(app)/(user)/org/billing/_components/available-plans.tsx @@ -7,7 +7,7 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; -import { features, pricingPlans } from "@/config/pricing"; +import { pricingFeatures, pricingPlans } from "@/config/pricing"; import { cn } from "@/lib/utils"; import type { OrgSubscription } from "@/types/org-subscription"; import { CheckIcon, XIcon } from "lucide-react"; @@ -44,7 +44,7 @@ export function AvailablePlans({ subscription }: AvailablePlansProps) { ))} - {features.map((feature) => ( + {pricingFeatures.map((feature) => (
  • +

    + Starterkit Features +

    + + Starterkit features are designed to help you build a robust + and scalable SaaS project. + +
    +
    + {features.map((feature, idx) => ( + + ))} +
    + + ); +} + +type FeatureCardProps = Feature & { + index: number; +}; + +function FeatureCard({ + title, + description, + image, + imageDark, + index, +}: FeatureCardProps) { + return ( +
    +
    +
    + {title} + + {imageDark && ( + {title} + )} +
    +
    + +
    +

    {title}

    + + {description} + +
    +
    + ); +} diff --git a/starterkits/saas/src/app/(web)/page.tsx b/starterkits/saas/src/app/(web)/page.tsx index 4b3a8e1..dd71e1f 100644 --- a/starterkits/saas/src/app/(web)/page.tsx +++ b/starterkits/saas/src/app/(web)/page.tsx @@ -1,3 +1,4 @@ +import Features from "@/app/(web)/_components/features"; import { WebPageHeader, WebPageWrapper, @@ -71,6 +72,8 @@ export default async function HomePage() { + + ); } diff --git a/starterkits/saas/src/app/(web)/pricing/_components/pricing-table.tsx b/starterkits/saas/src/app/(web)/pricing/_components/pricing-table.tsx index 2dfdb2c..52f425c 100644 --- a/starterkits/saas/src/app/(web)/pricing/_components/pricing-table.tsx +++ b/starterkits/saas/src/app/(web)/pricing/_components/pricing-table.tsx @@ -7,7 +7,11 @@ import { } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { CheckIcon, XIcon } from "lucide-react"; -import { type PrincingPlan, pricingPlans, features } from "@/config/pricing"; +import { + type PrincingPlan, + pricingPlans, + pricingFeatures, +} from "@/config/pricing"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { redirect } from "next/navigation"; @@ -104,7 +108,7 @@ function PricingCard({ pricing }: PricingCardProps) {
  • ))} - {features.map((feature) => ( + {pricingFeatures.map((feature) => (
  • Date: Mon, 22 Apr 2024 00:22:56 +0500 Subject: [PATCH 4/6] feat(saas): Testimonials to landing page --- .../app/(web)/_components/testimonials.tsx | 90 +++++++++++++++ starterkits/saas/src/app/(web)/page.tsx | 3 + starterkits/saas/src/config/testimonials.tsx | 104 ++++++++++++++++++ 3 files changed, 197 insertions(+) create mode 100644 starterkits/saas/src/app/(web)/_components/testimonials.tsx create mode 100644 starterkits/saas/src/config/testimonials.tsx diff --git a/starterkits/saas/src/app/(web)/_components/testimonials.tsx b/starterkits/saas/src/app/(web)/_components/testimonials.tsx new file mode 100644 index 0000000..962abb6 --- /dev/null +++ b/starterkits/saas/src/app/(web)/_components/testimonials.tsx @@ -0,0 +1,90 @@ +/* eslint-disable @next/next/no-img-element */ +import { featuredTestimonial, testimonials } from "@/config/testimonials"; +import { cn } from "@/lib/utils"; + +export function Testimonials() { + return ( +
    +
    +

    Testimonials

    +

    + People have said... +

    +
    + +
    +
    +
    +

    {`“${featuredTestimonial.body}”`}

    +
    +
    + +
    +
    + {featuredTestimonial.author.name} +
    +
    {`@${featuredTestimonial.author.handle}`}
    +
    + +
    +
    + {testimonials.map((columnGroup, columnGroupIdx) => ( +
    + {columnGroup.map((column, columnIdx) => ( +
    + {column.map((testimonial) => ( +
    +
    +

    {`“${testimonial.body}”`}

    +
    +
    + +
    +
    + {testimonial.author.name} +
    +
    {`@${testimonial.author.handle}`}
    +
    +
    +
    + ))} +
    + ))} +
    + ))} +
    +
    + ); +} diff --git a/starterkits/saas/src/app/(web)/page.tsx b/starterkits/saas/src/app/(web)/page.tsx index dd71e1f..bbbbdf5 100644 --- a/starterkits/saas/src/app/(web)/page.tsx +++ b/starterkits/saas/src/app/(web)/page.tsx @@ -4,6 +4,7 @@ import { WebPageWrapper, } from "@/app/(web)/_components/general-components"; import { Promotion } from "@/app/(web)/_components/promotion"; +import { Testimonials } from "@/app/(web)/_components/testimonials"; import { buttonVariants } from "@/components/ui/button"; import { Icons } from "@/components/ui/icons"; import { siteUrls } from "@/config/urls"; @@ -74,6 +75,8 @@ export default async function HomePage() { + + ); } diff --git a/starterkits/saas/src/config/testimonials.tsx b/starterkits/saas/src/config/testimonials.tsx new file mode 100644 index 0000000..d4bfef1 --- /dev/null +++ b/starterkits/saas/src/config/testimonials.tsx @@ -0,0 +1,104 @@ +/** + * This file is used to store the testimonials for the homepage. + * The testimonials are stored as an array of arrays of arrays. + * Each array represents a column of testimonials. + * Each inner array represents a row of testimonials. + * Each testimonial is an object with a body and author property. + * + * @note add your testimonials evenly + */ + +type Testimonial = { + body: string; + author: { + name: string; + handle: string; + imageUrl: string; + logoUrl?: string; + }; +}; + +export const featuredTestimonial: Testimonial = { + body: "Integer id nunc sit semper purus. Bibendum at lacus ut arcu blandit montes vitae auctor libero. Hac condimentum dignissim nibh vulputate ut nunc. Amet nibh orci mi venenatis blandit vel et proin. Non hendrerit in vel ac diam.", + author: { + name: "Brenna Goyette", + handle: "brennagoyette", + imageUrl: + "https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=1024&h=1024&q=80", + logoUrl: "https://tailwindui.com/img/logos/savvycal-logo-gray-900.svg", + }, +}; + +export const testimonials: Testimonial[][][] = [ + [ + [ + { + body: "Laborum quis quam. Dolorum et ut quod quia. Voluptas numquam delectus nihil. Aut enim doloremque et ipsam.", + author: { + name: "Leslie Alexander", + handle: "lesliealexander", + imageUrl: + "https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80", + }, + }, + { + body: "Aut reprehenderit voluptatem eum asperiores beatae id. Iure molestiae ipsam ut officia rem nulla blanditiis.", + author: { + name: "Lindsay Walton", + handle: "lindsaywalton", + imageUrl: + "https://images.unsplash.com/photo-1517841905240-472988babdf9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80", + }, + }, + // More testimonials... + ], + [ + { + body: "Aut reprehenderit voluptatem eum asperiores beatae id. Iure molestiae ipsam ut officia rem nulla blanditiis.", + author: { + name: "Lindsay Walton", + handle: "lindsaywalton", + imageUrl: + "https://images.unsplash.com/photo-1517841905240-472988babdf9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80", + }, + }, + // More testimonials... + ], + ], + [ + [ + { + body: "Voluptas quos itaque ipsam in voluptatem est. Iste eos blanditiis repudiandae. Earum deserunt enim molestiae ipsum perferendis recusandae saepe corrupti.", + author: { + name: "Tom Cook", + handle: "tomcook", + imageUrl: + "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80", + }, + }, + + // More testimonials... + ], + [ + { + body: "Molestias ea earum quos nostrum doloremque sed. Quaerat quasi aut velit incidunt excepturi rerum voluptatem minus harum.", + author: { + name: "Leonard Krasner", + handle: "leonardkrasner", + imageUrl: + "https://images.unsplash.com/photo-1519345182560-3f2917c472ef?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80", + }, + }, + { + body: "Voluptas quos itaque ipsam in voluptatem est. Iste eos blanditiis repudiandae. Earum deserunt enim molestiae ipsum perferendis recusandae saepe corrupti.", + author: { + name: "Tom Cook", + handle: "tomcook", + imageUrl: + "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80", + }, + }, + // More testimonials... + ], + ], +]; From a943ef0a9b54a6655e25deb486d280f734571a4a Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Mon, 22 Apr 2024 00:29:43 +0500 Subject: [PATCH 5/6] refactor(saas): Updated features landing ui --- starterkits/saas/src/app/(web)/_components/features.tsx | 4 ++-- starterkits/saas/src/config/features.ts | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/starterkits/saas/src/app/(web)/_components/features.tsx b/starterkits/saas/src/app/(web)/_components/features.tsx index 3f8a61c..582ed94 100644 --- a/starterkits/saas/src/app/(web)/_components/features.tsx +++ b/starterkits/saas/src/app/(web)/_components/features.tsx @@ -18,7 +18,7 @@ export default function Features() { and scalable SaaS project. -
    +
    {features.map((feature, idx) => ( +
    Date: Mon, 22 Apr 2024 02:31:30 +0500 Subject: [PATCH 6/6] feat(saas): Added footer --- .../src/app/(app)/_components/sidebar.tsx | 2 +- .../saas/src/app/(web)/_components/footer.tsx | 131 ++++++++++++++++++ starterkits/saas/src/app/(web)/layout.tsx | 2 + starterkits/saas/src/config/header.ts | 1 + starterkits/saas/src/config/site.ts | 2 + 5 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 starterkits/saas/src/app/(web)/_components/footer.tsx diff --git a/starterkits/saas/src/app/(app)/_components/sidebar.tsx b/starterkits/saas/src/app/(app)/_components/sidebar.tsx index 0021a2c..6fa5159 100644 --- a/starterkits/saas/src/app/(app)/_components/sidebar.tsx +++ b/starterkits/saas/src/app/(app)/_components/sidebar.tsx @@ -54,7 +54,7 @@ export async function Sidebar({
    ); diff --git a/starterkits/saas/src/config/header.ts b/starterkits/saas/src/config/header.ts index 22306a9..cce1b03 100644 --- a/starterkits/saas/src/config/header.ts +++ b/starterkits/saas/src/config/header.ts @@ -19,6 +19,7 @@ interface NavigationItem { href: string; label: string; badge?: string; + external?: boolean; } export const navigation: NavigationItem[] = [ diff --git a/starterkits/saas/src/config/site.ts b/starterkits/saas/src/config/site.ts index 9b20184..9574491 100644 --- a/starterkits/saas/src/config/site.ts +++ b/starterkits/saas/src/config/site.ts @@ -6,6 +6,8 @@ export const siteConfig = { name: "RapidLaunch", + description: + "Build your SaaS with ease, using our beautiful starterkit. Rapidlaunch is a powerful and flexible SaaS platform that allows you to build and deploy your SaaS quickly and easily.", contactEmail: "hello@support.rapidlaunch.xyz", noReplyEmail: "Rapidlaunch@support.rapidlaunch.xyz", } as const;