├── .env.example ├── .eslintrc.cjs ├── .gitignore ├── LICENSE ├── README.md ├── components.json ├── cursorrules ├── next-sitemap.config.cjs ├── next.config.js ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── prettier.config.js ├── prisma └── schema.prisma ├── public ├── favicon.ico └── sitemap.xml ├── sentry.client.config.ts ├── sentry.edge.config.ts ├── sentry.server.config.ts ├── src ├── app │ ├── (marketing) │ │ ├── (home) │ │ │ └── page.tsx │ │ └── layout.tsx │ ├── (saas) │ │ ├── app │ │ │ └── page.tsx │ │ └── layout.tsx │ ├── api │ │ ├── sentry-example-api │ │ │ └── route.ts │ │ └── trpc │ │ │ └── [trpc] │ │ │ └── route.ts │ ├── dashboard │ │ └── page.tsx │ ├── global-error.tsx │ ├── handler │ │ └── [...stack] │ │ │ └── page.tsx │ ├── layout.tsx │ ├── loading.tsx │ └── sentry-example-page │ │ └── page.tsx ├── components │ ├── emails │ │ └── email-template.tsx │ ├── marketing │ │ ├── features │ │ │ ├── animated-beam-multiple-outputs.tsx │ │ │ └── animated-list-demo.tsx │ │ ├── hero │ │ │ ├── assurance-items.tsx │ │ │ ├── hero-banner.tsx │ │ │ ├── hero-title.tsx │ │ │ └── testimonials-avatars.tsx │ │ ├── pricing │ │ │ └── plan-card.tsx │ │ ├── sections │ │ │ ├── feature-section.tsx │ │ │ ├── hero-section.tsx │ │ │ └── pricing-section.tsx │ │ ├── shared │ │ │ ├── footer.tsx │ │ │ ├── navbar.tsx │ │ │ └── section-title.tsx │ │ └── testimonials │ │ │ └── testimonials.tsx │ ├── saas │ │ ├── app-sidebar.tsx │ │ ├── nav-main.tsx │ │ ├── nav-projects.tsx │ │ ├── nav-secondary.tsx │ │ ├── nav-user.tsx │ │ └── post.tsx │ └── ui │ │ ├── animated-beam.tsx │ │ ├── animated-grid-pattern.tsx │ │ ├── animated-list.tsx │ │ ├── animated-shiny-text.tsx │ │ ├── avatar-circles.tsx │ │ ├── avatar.tsx │ │ ├── badge.tsx │ │ ├── bento-grid.tsx │ │ ├── breadcrumb.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── collapsible.tsx │ │ ├── container.tsx │ │ ├── dropdown-menu.tsx │ │ ├── gradient-text.tsx │ │ ├── hero-video-dialog.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── marquee.tsx │ │ ├── rainbow-button.tsx │ │ ├── separator.tsx │ │ ├── sheet.tsx │ │ ├── sidebar.tsx │ │ ├── skeleton.tsx │ │ ├── switch.tsx │ │ ├── tooltip.tsx │ │ └── tracing-beam.tsx ├── env.js ├── hooks │ └── use-mobile.tsx ├── instrumentation.ts ├── lib │ ├── mail.ts │ ├── posthog.ts │ └── utils.ts ├── provider │ └── posthog-provider.tsx ├── server │ ├── api │ │ ├── root.ts │ │ ├── routers │ │ │ ├── email.ts │ │ │ └── post.ts │ │ └── trpc.ts │ └── db.ts ├── stack.tsx ├── styles │ └── globals.css ├── trpc │ ├── query-client.ts │ ├── react.tsx │ └── server.ts └── types │ └── pricing.ts ├── start-database.sh ├── tailwind.config.ts └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | # Since the ".env" file is gitignored, you can use the ".env.example" file to 2 | # build a new ".env" file when you clone the repo. Keep this file up-to-date 3 | # when you add new variables to `.env`. 4 | 5 | # This file will be committed to version control, so make sure not to have any 6 | # secrets in it. If you are cloning this repo, create a copy of this file named 7 | # ".env" and populate it with your secrets. 8 | 9 | # When adding additional environment variables, the schema in "/src/env.js" 10 | # should be updated accordingly. 11 | 12 | # Prisma (Required) 13 | # https://www.prisma.io/docs/reference/database-reference/connection-urls#env 14 | DATABASE_URL="postgresql://postgres:password@localhost:5432/saas-boilerplate" 15 | 16 | # Stack Auth (Required) 17 | # https://docs.stack-auth.com/overview 18 | NEXT_PUBLIC_STACK_PROJECT_ID="" 19 | NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY="" 20 | STACK_SECRET_SERVER_KEY="" 21 | 22 | # Sentry (Optional) 23 | SENTRY_ORG="" 24 | SENTRY_PROJECT="" 25 | 26 | # Resend (Optional) 27 | RESEND_API_KEY="" 28 | RESEND_AUDIENCE_ID="" 29 | 30 | # PostHog 31 | NEXT_PUBLIC_POSTHOG_HOST="" 32 | NEXT_PUBLIC_POSTHOG_KEY="" -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | const config = { 3 | "parser": "@typescript-eslint/parser", 4 | "parserOptions": { 5 | "project": true 6 | }, 7 | "plugins": [ 8 | "@typescript-eslint" 9 | ], 10 | "extends": [ 11 | "next/core-web-vitals", 12 | "plugin:@typescript-eslint/recommended-type-checked", 13 | "plugin:@typescript-eslint/stylistic-type-checked" 14 | ], 15 | "rules": { 16 | "@typescript-eslint/array-type": "off", 17 | "@typescript-eslint/consistent-type-definitions": "off", 18 | "@typescript-eslint/consistent-type-imports": [ 19 | "warn", 20 | { 21 | "prefer": "type-imports", 22 | "fixStyle": "inline-type-imports" 23 | } 24 | ], 25 | "@typescript-eslint/no-unused-vars": [ 26 | "warn", 27 | { 28 | "argsIgnorePattern": "^_" 29 | } 30 | ], 31 | "@typescript-eslint/require-await": "off", 32 | "@typescript-eslint/no-misused-promises": [ 33 | "error", 34 | { 35 | "checksVoidReturn": { 36 | "attributes": false 37 | } 38 | } 39 | ], 40 | "@typescript-eslint/ban-ts-comment": "off" 41 | } 42 | } 43 | module.exports = config; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # database 12 | /prisma/db.sqlite 13 | /prisma/db.sqlite-journal 14 | db.sqlite 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | next-env.d.ts 20 | 21 | # production 22 | /build 23 | 24 | # misc 25 | .DS_Store 26 | *.pem 27 | 28 | # debug 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | .pnpm-debug.log* 33 | 34 | # local env files 35 | # do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables 36 | .env 37 | .env*.local 38 | 39 | # vercel 40 | .vercel 41 | 42 | # typescript 43 | *.tsbuildinfo 44 | 45 | # idea files 46 | .idea 47 | # Sentry Config File 48 | .env.sentry-build-plugin 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Robin Faraj 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |
3 | SaaS Boilerplate 4 |
5 |

6 | 7 |

A modern, type-safe SaaS boilerplate built with Next.js 15, tRPC, and Prisma.

8 | 9 |

10 | Key Features • 11 | Tech Stack • 12 | Quick Start • 13 | Project Structure 14 |

15 | 16 |

17 | 18 | License 19 | 20 |

21 | 22 |

23 | Looking for a mobile app boilerplate? Check out NativeExpress - The ultimate React Native & Expo boilerplate! 24 |

25 | 26 | ## Key Features 27 | 28 | * Full-stack type safety with TypeScript and tRPC 29 | * Modern file-based routing with Next.js 15 App Router 30 | * Beautiful UI components from ShadcN and MagicUI 31 | * Secure database management with Prisma and PostgreSQL 32 | * Real-time analytics with PostHog 33 | * Responsive design with TailwindCSS 34 | * Dark/Light mode support 35 | * End-to-end type safety from database to frontend 36 | * Production-ready authentication system 37 | * Optimized data fetching with React Query 38 | 39 | ## Tech Stack 40 | 41 | * **Framework**: Next.js 15 with App Router 42 | * **Language**: TypeScript 43 | * **API**: tRPC for end-to-end type-safe APIs 44 | * **Database**: PostgreSQL with Prisma ORM 45 | * **UI Components**: ShadcN UI & MagicUI 46 | * **Styling**: TailwindCSS 47 | * **Analytics**: PostHog 48 | * **Data Fetching**: React Query (through tRPC) 49 | * **Validation**: Zod 50 | 51 | ## Quick Start 52 | 53 | 1. Clone the repository: 54 | ```bash 55 | git clone https://github.com/robinsadeghpour/saas-boilerplate.git 56 | cd saas-boilerplate 57 | ``` 58 | 59 | 2. Install dependencies: 60 | ```bash 61 | pnpm install 62 | ``` 63 | 64 | 3. Copy the environment variables: 65 | ```bash 66 | cp .env.example .env 67 | ``` 68 | 69 | 4. Start the PostgreSQL database: 70 | ```bash 71 | ./start-database.sh 72 | ``` 73 | 74 | 5. Run database migrations: 75 | ```bash 76 | pnpm prisma migrate dev 77 | ``` 78 | 79 | 6. Start the development server: 80 | ```bash 81 | pnpm dev 82 | ``` 83 | 84 | ## Project Structure 85 | 86 | ``` 87 | src/ 88 | ├── app/ # Next.js App Router pages and layouts 89 | ├── components/ # Reusable UI components 90 | ├── hooks/ # Custom React hooks 91 | ├── lib/ # Core utilities and services 92 | ├── provider/ # Context providers and wrappers 93 | ├── server/ # Server-side logic 94 | ├── styles/ # Global styles and Tailwind config 95 | ├── trpc/ # tRPC router and procedures 96 | └── types/ # TypeScript types and interfaces 97 | ``` 98 | 99 | ## Development Guidelines 100 | 101 | * Use TypeScript for all files except configurations 102 | * Follow functional component patterns with hooks 103 | * Keep components focused and small 104 | * Use Tailwind for styling with consistent design tokens 105 | * Follow mobile-first responsive design 106 | * Implement proper error handling with tRPC 107 | * Use React Query features through tRPC for data management 108 | 109 | ## Related Projects 110 | 111 | 🚀 **[NativeExpress](https://native.express?ref=saas-boilerplate)** - The ultimate React Native & Expo boilerplate with all the features you need to build production-ready mobile apps. 112 | 113 | --- 114 | 115 |

116 | Follow on X • 117 | Subscribe on YouTube 118 |

119 | 120 | > This project is maintained by [Robin Faraj](https://x.com/robin_faraj?ref=saas-boilerplate) 121 | 122 | ## Environment Variables 123 | 124 | ### Required Environment Variables 125 | The following environment variables are required for the application to function properly: 126 | 127 | - `DATABASE_URL`: PostgreSQL connection URL 128 | - `NEXT_PUBLIC_STACK_PROJECT_ID`: Your Stack Auth project ID 129 | - `NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY`: Your Stack Auth publishable client key 130 | - `STACK_SECRET_SERVER_KEY`: Your Stack Auth secret server key 131 | 132 | ### Optional Environment Variables 133 | These environment variables are optional but enable additional features: 134 | 135 | - `RESEND_API_KEY`: For email functionality 136 | - `RESEND_AUDIENCE_ID`: For newsletter management 137 | - `SENTRY_ORG` and `SENTRY_PROJECT`: For error tracking 138 | - `NEXT_PUBLIC_POSTHOG_HOST` and `NEXT_PUBLIC_POSTHOG_KEY`: For analytics 139 | 140 | ### Setup Instructions 141 | 142 | 1. Copy `.env.example` to `.env` 143 | 144 | 2. Set up the database: 145 | - Make sure Docker is installed and running 146 | - Start the local database using the provided script: 147 | ```bash 148 | ./start-database.sh 149 | ``` 150 | - Push the database schema: 151 | ```bash 152 | pnpm db:push 153 | ``` 154 | 155 | 3. For Stack Auth credentials: 156 | - Visit [Stack Auth Documentation](https://docs.stack-auth.com/overview) 157 | - Follow their setup guide to obtain your project credentials 158 | - Fill in the corresponding environment variables 159 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/styles/globals.css", 9 | "baseColor": "zinc", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /cursorrules: -------------------------------------------------------------------------------- 1 | You are an expert in TypeScript, Next.js, and full-stack development, specializing in creating clean, modular code with modern best practices. 2 | 3 | # Tech Stack 4 | - Next.js 15 with App Router for file-based routing 5 | - TypeScript for type-safe development 6 | - tRPC for end-to-end typesafe APIs 7 | - Prisma with PostgreSQL for database management 8 | - ShadcN UI for component library 9 | - MagicUI for enhanced UI components 10 | - TailwindCSS for styling 11 | - PostHog for analytics 12 | - React Query (through tRPC) for data fetching 13 | - Zod for schema validation 14 | 15 | # Project Structure 16 | /src/app/** -> Next.js App Router pages and layouts 17 | /src/components/** -> Reusable UI components 18 | /src/hooks/** -> Custom React hooks 19 | /src/lib/** -> Core utilities and services 20 | /src/provider/** -> Context providers and wrappers 21 | /src/server/** -> Server-side logic 22 | /src/styles/** -> Global styles and Tailwind configurations 23 | /src/trpc/** -> tRPC router and procedures 24 | /src/types/** -> TypeScript types and interfaces 25 | /prisma/** -> Database schema and migrations 26 | 27 | # Coding Standards 28 | - Use TypeScript for all files except configurations 29 | - Implement functional components with hooks 30 | - Keep components focused and small (< 200 lines) 31 | - Use Tailwind for styling with consistent design tokens 32 | - Follow mobile-first responsive design 33 | - Implement proper error handling with tRPC 34 | - Use React Query features through tRPC for data management 35 | 36 | # Import Patterns 37 | - Use absolute imports with @ prefix 38 | - Import UI components from @/components/ui 39 | - Import server procedures from @/server/api 40 | - Import types from @/types 41 | - Import hooks from @/hooks 42 | 43 | # Style Guidelines 44 | - Use ShadcN UI components from @/components/ui 45 | - Implement className="..." for Tailwind styling 46 | - Support dark mode with next-themes 47 | - Follow mobile-first responsive design 48 | - Use semantic class names and design tokens 49 | 50 | # Type Safety 51 | - Use interfaces for complex objects, type for simple ones 52 | - Use Zod for runtime validation 53 | - Leverage tRPC's type inference 54 | - Avoid any type unless absolutely necessary 55 | - Use strict TypeScript configurations 56 | 57 | # Component Pattern 58 | ```typescript 59 | import { type ComponentProps } from 'react'; 60 | import { cn } from '@/lib/utils'; 61 | 62 | interface Props extends ComponentProps<'div'> { 63 | title: string; 64 | } 65 | 66 | export function Component({ 67 | title, 68 | className, 69 | ...props 70 | }: Props) { 71 | return ( 72 |
79 | {/* Component content */} 80 |
81 | ); 82 | } 83 | ``` 84 | 85 | # tRPC Router Pattern 86 | ```typescript 87 | import { z } from 'zod'; 88 | import { createTRPCRouter, publicProcedure, protectedProcedure } from '../trpc'; 89 | 90 | export const router = createTRPCRouter({ 91 | create: protectedProcedure 92 | .input(z.object({ 93 | // validation schema 94 | })) 95 | .mutation(async ({ ctx, input }) => { 96 | // implementation 97 | }), 98 | }); 99 | ``` 100 | 101 | # Prisma Pattern 102 | ```typescript 103 | // prisma/schema.prisma 104 | model User { 105 | id String @id @default(cuid()) 106 | email String @unique 107 | name String? 108 | createdAt DateTime @default(now()) 109 | updatedAt DateTime @updatedAt 110 | } 111 | ``` -------------------------------------------------------------------------------- /next-sitemap.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next-sitemap').IConfig} */ 2 | module.exports = { 3 | siteUrl: process.env.SITE_URL ?? "https://example.com", 4 | generateRobotsTxt: false, 5 | }; 6 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful 3 | * for Docker builds. 4 | */ 5 | import "./src/env.js"; 6 | import { withSentryConfig } from "@sentry/nextjs"; 7 | 8 | /** @type {import("next").NextConfig} */ 9 | const config = { 10 | images: { 11 | remotePatterns: [ 12 | { 13 | // google profile images 14 | protocol: "https", 15 | hostname: "lh3.googleusercontent.com", 16 | }, 17 | { 18 | // github profile images 19 | protocol: "https", 20 | hostname: "avatars.githubusercontent.com", 21 | }, 22 | { 23 | // vercel profile images 24 | protocol: "https", 25 | hostname: "avatar.vercel.sh", 26 | }, 27 | { 28 | // vercel profile images 29 | protocol: "https", 30 | hostname: "startup-template-sage.vercel.app", 31 | }, 32 | { 33 | // supabase profile images 34 | protocol: "https", 35 | hostname: "qpdwualqgmqaxfgoapyc.supabase.co", 36 | }, 37 | ], 38 | }, 39 | }; 40 | 41 | // Sentry configuration 42 | const sentryConfig = { 43 | org: process.env.SENTRY_ORG, 44 | project: process.env.SENTRY_PROJECT, 45 | 46 | // Only print logs for uploading source maps in CI 47 | silent: !process.env.CI, 48 | 49 | 50 | // For all available options, see: 51 | // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ 52 | 53 | 54 | // For all available options, see: 55 | // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ 56 | 57 | // Upload a larger set of source maps for prettier stack traces (increases build time) 58 | widenClientFileUpload: true, 59 | 60 | // Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers 61 | tunnelRoute: "/monitoring", 62 | 63 | // Hides source maps from generated client bundles 64 | hideSourceMaps: true, 65 | 66 | // Automatically tree-shake Sentry logger statements to reduce bundle size 67 | disableLogger: true, 68 | 69 | // Enables automatic instrumentation of Vercel Cron Monitors 70 | automaticVercelMonitors: true, 71 | }; 72 | 73 | export default withSentryConfig(config, sentryConfig); 74 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "saas-boilerplate", 3 | "version": "0.1.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "build": "next build", 8 | "postbuild": "next-sitemap --config next-sitemap.config.cjs", 9 | "check": "next lint && tsc --noEmit", 10 | "db:generate": "prisma migrate dev", 11 | "db:migrate": "prisma migrate deploy", 12 | "db:push": "prisma db push", 13 | "db:studio": "prisma studio", 14 | "dev": "next dev --turbo", 15 | "format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,mdx}\" --cache", 16 | "format:write": "prettier --write \"**/*.{ts,tsx,js,jsx,mdx}\" --cache", 17 | "postinstall": "prisma generate", 18 | "lint": "next lint", 19 | "lint:fix": "next lint --fix", 20 | "preview": "next build && next start", 21 | "start": "next start", 22 | "typecheck": "tsc --noEmit" 23 | }, 24 | "dependencies": { 25 | "@prisma/client": "^6.1.0", 26 | "@radix-ui/react-avatar": "^1.1.2", 27 | "@radix-ui/react-collapsible": "^1.1.2", 28 | "@radix-ui/react-dialog": "^1.1.4", 29 | "@radix-ui/react-dropdown-menu": "^2.1.4", 30 | "@radix-ui/react-icons": "^1.3.2", 31 | "@radix-ui/react-label": "^2.1.1", 32 | "@radix-ui/react-separator": "^1.1.1", 33 | "@radix-ui/react-slot": "^1.1.1", 34 | "@radix-ui/react-switch": "^1.1.2", 35 | "@radix-ui/react-tooltip": "^1.1.6", 36 | "@react-email/components": "^0.0.31", 37 | "@sentry/nextjs": "^8", 38 | "@stackframe/stack": "^2.6.39", 39 | "@t3-oss/env-nextjs": "^0.10.1", 40 | "@tanstack/react-query": "^5.50.0", 41 | "@trpc/client": "^11.0.0-rc.446", 42 | "@trpc/react-query": "^11.0.0-rc.446", 43 | "@trpc/server": "^11.0.0-rc.446", 44 | "class-variance-authority": "^0.7.1", 45 | "clsx": "^2.1.1", 46 | "framer-motion": "^11.15.0", 47 | "geist": "^1.3.0", 48 | "lucide-react": "^0.469.0", 49 | "next": "^15.0.1", 50 | "next-sitemap": "^4.2.3", 51 | "posthog-js": "^1.203.1", 52 | "posthog-node": "^4.3.2", 53 | "react": "^18.3.1", 54 | "react-dom": "^18.3.1", 55 | "react-email": "^3.0.4", 56 | "resend": "^4.0.1", 57 | "server-only": "^0.0.1", 58 | "superjson": "^2.2.1", 59 | "tailwind-merge": "^2.5.5", 60 | "tailwindcss-animate": "^1.0.7", 61 | "zod": "^3.23.3" 62 | }, 63 | "devDependencies": { 64 | "@types/eslint": "^8.56.10", 65 | "@types/node": "^20.14.10", 66 | "@types/react": "^18.3.3", 67 | "@types/react-dom": "^18.3.0", 68 | "@typescript-eslint/eslint-plugin": "^8.1.0", 69 | "@typescript-eslint/parser": "^8.1.0", 70 | "eslint": "^8.57.0", 71 | "eslint-config-next": "^15.0.1", 72 | "postcss": "^8.4.39", 73 | "prettier": "^3.3.2", 74 | "prettier-plugin-tailwindcss": "^0.6.5", 75 | "prisma": "^5.14.0", 76 | "tailwindcss": "^3.4.3", 77 | "typescript": "^5.5.3" 78 | }, 79 | "ct3aMetadata": { 80 | "initVersion": "7.38.1" 81 | }, 82 | "packageManager": "pnpm@9.9.0" 83 | } 84 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */ 2 | export default { 3 | plugins: ["prettier-plugin-tailwindcss"], 4 | }; 5 | -------------------------------------------------------------------------------- /prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "prisma-client-js" 6 | } 7 | 8 | datasource db { 9 | provider = "postgresql" 10 | url = env("DATABASE_URL") 11 | } 12 | 13 | model Post { 14 | id Int @id @default(autoincrement()) 15 | name String 16 | createdAt DateTime @default(now()) 17 | updatedAt DateTime @updatedAt 18 | 19 | @@index([name]) 20 | } 21 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinfaraj/saas-boilerplate/4eab0ba953fa1d4d2de58d28c371b075142e069e/public/favicon.ico -------------------------------------------------------------------------------- /public/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /sentry.client.config.ts: -------------------------------------------------------------------------------- 1 | // This file configures the initialization of Sentry on the client. 2 | // The config you add here will be used whenever a users loads a page in their browser. 3 | // https://docs.sentry.io/platforms/javascript/guides/nextjs/ 4 | 5 | import * as Sentry from "@sentry/nextjs"; 6 | 7 | Sentry.init({ 8 | dsn: "https://52fc7cd5d5f21b308f7460a3ac02b676@o4507856717938688.ingest.de.sentry.io/4507856718659664", 9 | 10 | // Add optional integrations for additional features 11 | integrations: [Sentry.replayIntegration()], 12 | 13 | // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. 14 | tracesSampleRate: 1, 15 | 16 | // Define how likely Replay events are sampled. 17 | // This sets the sample rate to be 10%. You may want this to be 100% while 18 | // in development and sample at a lower rate in production 19 | replaysSessionSampleRate: 0.1, 20 | 21 | // Define how likely Replay events are sampled when an error occurs. 22 | replaysOnErrorSampleRate: 1.0, 23 | 24 | // Setting this option to true will print useful information to the console while you're setting up Sentry. 25 | debug: false, 26 | }); 27 | -------------------------------------------------------------------------------- /sentry.edge.config.ts: -------------------------------------------------------------------------------- 1 | // This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on). 2 | // The config you add here will be used whenever one of the edge features is loaded. 3 | // Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally. 4 | // https://docs.sentry.io/platforms/javascript/guides/nextjs/ 5 | 6 | import * as Sentry from "@sentry/nextjs"; 7 | 8 | Sentry.init({ 9 | dsn: "https://52fc7cd5d5f21b308f7460a3ac02b676@o4507856717938688.ingest.de.sentry.io/4507856718659664", 10 | 11 | // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. 12 | tracesSampleRate: 1, 13 | 14 | // Setting this option to true will print useful information to the console while you're setting up Sentry. 15 | debug: false, 16 | }); 17 | -------------------------------------------------------------------------------- /sentry.server.config.ts: -------------------------------------------------------------------------------- 1 | // This file configures the initialization of Sentry on the server. 2 | // The config you add here will be used whenever the server handles a request. 3 | // https://docs.sentry.io/platforms/javascript/guides/nextjs/ 4 | 5 | import * as Sentry from "@sentry/nextjs"; 6 | 7 | Sentry.init({ 8 | dsn: "https://52fc7cd5d5f21b308f7460a3ac02b676@o4507856717938688.ingest.de.sentry.io/4507856718659664", 9 | 10 | // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. 11 | tracesSampleRate: 1, 12 | 13 | // Setting this option to true will print useful information to the console while you're setting up Sentry. 14 | debug: false, 15 | }); 16 | -------------------------------------------------------------------------------- /src/app/(marketing)/(home)/page.tsx: -------------------------------------------------------------------------------- 1 | import { HeroSection } from "@/components/marketing/sections/hero-section"; 2 | import { PricingSection } from "@/components/marketing/sections/pricing-section"; 3 | import { Testimonials } from "@/components/marketing/testimonials/testimonials"; 4 | import { FeatureSection } from "@/components/marketing/sections/feature-section"; 5 | 6 | 7 | export default function MarketingPage() { 8 | return ( 9 | <> 10 | 11 | 12 | 13 | 14 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /src/app/(marketing)/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Footer } from "@/components/marketing/shared/footer"; 2 | import { NavBar } from "@/components/marketing/shared/navbar"; 3 | import type { PropsWithChildren } from "react"; 4 | 5 | export default async function MarketingLayout({ children }: PropsWithChildren) { 6 | return ( 7 | <> 8 | 9 |
{children}
10 |