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/(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) => (
  • + + {children} + + ); +} diff --git a/starterkits/saas/src/app/(web)/_components/features.tsx b/starterkits/saas/src/app/(web)/_components/features.tsx new file mode 100644 index 0000000..582ed94 --- /dev/null +++ b/starterkits/saas/src/app/(web)/_components/features.tsx @@ -0,0 +1,90 @@ +import { type Feature, features } from "@/config/features"; +import { cn } from "@/lib/utils"; +import Image from "next/image"; +import Balancer from "react-wrap-balancer"; + +export default function Features() { + return ( +
    +
    +

    + 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)/_components/footer.tsx b/starterkits/saas/src/app/(web)/_components/footer.tsx new file mode 100644 index 0000000..84d4dda --- /dev/null +++ b/starterkits/saas/src/app/(web)/_components/footer.tsx @@ -0,0 +1,131 @@ +import { ThemeToggle } from "@/components/theme-toggle"; +import { buttonVariants } from "@/components/ui/button"; +import { Icons } from "@/components/ui/icons"; +import { navigation } from "@/config/header"; +import { siteConfig } from "@/config/site"; +import { siteUrls } from "@/config/urls"; +import { cn } from "@/lib/utils"; +import { ArrowUpRightIcon, BookOpenIcon } from "lucide-react"; +import Link from "next/link"; +import Balancer from "react-wrap-balancer"; + +export function WebFooter() { + return ( +
    +
    +
    +
    + + + + + {siteConfig.description} + +
    + +
    + + + + + + + +
    +
    +
    +
    +

    Resources

    + {navigation.map((item) => ( + + ))} + +
    +
    +

    Usefull links

    + {navigation.map((item) => ( + + ))} +
    +
    +

    More

    + {navigation.map((item) => ( + + ))} +
    +
    +
    +
    + ); +} + +interface FooterLinkProps { + href: string; + label: string; + external?: boolean; +} + +function FooterLink({ href, label, external = false }: FooterLinkProps) { + const isExternal = external || href.startsWith("http"); + + const externalProps = isExternal + ? { + target: "_blank", + rel: "noreferrer", + } + : {}; + + return ( + + {label} + {isExternal ? ( + + ) : null} + + ); +} diff --git a/starterkits/saas/src/app/(web)/_components/general-components.tsx b/starterkits/saas/src/app/(web)/_components/general-components.tsx index 0d172cb..9119b25 100644 --- a/starterkits/saas/src/app/(web)/_components/general-components.tsx +++ b/starterkits/saas/src/app/(web)/_components/general-components.tsx @@ -28,7 +28,7 @@ export function WebPageWrapper({ } // This is a page heading used in all public web pages -export function WebPageHeading({ +export function WebPageHeader({ title, badge, children, @@ -46,7 +46,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)/_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)/_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)/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)/layout.tsx b/starterkits/saas/src/app/(web)/layout.tsx index 5764924..3977a4e 100644 --- a/starterkits/saas/src/app/(web)/layout.tsx +++ b/starterkits/saas/src/app/(web)/layout.tsx @@ -1,3 +1,5 @@ +import { Background } from "@/app/(web)/_components/background"; +import { WebFooter } from "@/app/(web)/_components/footer"; import { WebHeader } from "@/app/(web)/_components/header"; type WebLayoutProps = { @@ -7,8 +9,11 @@ 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 c6a2cb3..bbbbdf5 100644 --- a/starterkits/saas/src/app/(web)/page.tsx +++ b/starterkits/saas/src/app/(web)/page.tsx @@ -1,3 +1,82 @@ +import Features from "@/app/(web)/_components/features"; +import { + WebPageHeader, + 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"; +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/_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) => (
  • - @@ -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) => ( diff --git a/starterkits/saas/src/config/features.ts b/starterkits/saas/src/config/features.ts new file mode 100644 index 0000000..a5d05c5 --- /dev/null +++ b/starterkits/saas/src/config/features.ts @@ -0,0 +1,52 @@ +/** + * This file contains the features data for the features page. + * + * @add a new feature, add a new object to the `features` array. + * 1. Add id to the features object then use it as the id of the new feature object. + * 2. Add title and inludedIn to the new feature object. (inludedIn is an array of pricing plan ids that include this feature) + * 3. Add description to the new feature object. + * 4. Add image to the new feature object. + * 5. Add imageDark to the new feature object. (optional) + */ + +export type Feature = { + title: string; + description: string; + image: string; + imageDark?: string; +}; + +export const features: Feature[] = [ + { + title: "Dashboard", + description: + "Rapidlaunch provides a powerful dashboard that allows you to manage your SaaS project. With our starterkits, components, and building guides, you can quickly set up a robust dashboard for your project.", + image: "https://utfs.io/f/43bbc3c8-cf3c-4fae-a0eb-9183f1779489-294m81.png", + imageDark: + "https://utfs.io/f/fddea366-51c6-45f4-bd54-84d273ad9fb9-1ly324.png", + }, + { + title: "Authentication", + description: + "Rapidlaunch provides a secure authentication system that allows users to sign up and log in to your SaaS. With our starterkits, components, and building guides, you can quickly set up a robust authentication system for your project.", + image: "https://utfs.io/f/805616c1-22b8-4508-9890-9ba9e2867a41-p24dnn.png", + imageDark: + "https://utfs.io/f/9074c0de-d9ea-4c0b-9d49-55dca1253a3f-6ig3yq.png", + }, + { + title: "Organizational level Payments", + description: + "Rapidlaunch provides a flexible payment system that allows you to manage your SaaS project's payments. With our starterkits, components, and building guides, you can quickly set up a robust payment system for your project.", + image: "https://utfs.io/f/43bbc3c8-cf3c-4fae-a0eb-9183f1779489-294m81.png", + imageDark: + "https://utfs.io/f/fddea366-51c6-45f4-bd54-84d273ad9fb9-1ly324.png", + }, + { + title: "User Management", + description: + "Rapidlaunch provides a user management system that allows you to manage your SaaS project's users. With our starterkits, components, and building guides, you can quickly set up a robust user management system for your project.", + image: "https://utfs.io/f/72a2c035-69e0-46ca-84a8-446e4dabf77c-3koi6e.png", + imageDark: + "https://utfs.io/f/89099112-4273-4375-9e44-1b3394600e21-c6ikq1.png", + }, +]; 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/pricing.ts b/starterkits/saas/src/config/pricing.ts index 55a7c30..8f02aeb 100644 --- a/starterkits/saas/src/config/pricing.ts +++ b/starterkits/saas/src/config/pricing.ts @@ -34,7 +34,7 @@ export type PrincingPlan = { }; }; -export type Feature = { +export type PricingFeature = { id: string; title: string; inludedIn: string[]; @@ -46,7 +46,7 @@ const pricingIds = { premium: "premium", } as const; -export const features: Feature[] = [ +export const pricingFeatures: PricingFeature[] = [ { id: "1", title: "SSO with unlimited social connections and MFA", 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; 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... + ], + ], +];