├── .changeset ├── README.md └── config.json ├── .github └── workflows │ ├── pull_request.yaml │ └── release.yml ├── .gitignore ├── .husky └── pre-commit ├── .idea ├── .gitignore ├── inspectionProfiles │ └── Project_Default.xml ├── jsLibraryMappings.xml ├── modules.xml ├── mudd-app.iml └── vcs.xml ├── .npmrc ├── .prettierrc ├── .vscode ├── extensions.json └── settings.json ├── README.md ├── apps ├── app │ ├── .env.local.example │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README.md │ ├── lib │ │ └── supabase │ │ │ └── server.ts │ ├── middleware.ts │ ├── next.config.js │ ├── package.json │ ├── postcss.config.js │ ├── public │ │ ├── apple-touch-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon.ico │ │ ├── next.svg │ │ └── vercel.svg │ ├── src │ │ ├── app │ │ │ ├── (splash) │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ │ ├── app │ │ │ │ ├── actions │ │ │ │ │ └── user.ts │ │ │ │ ├── layout.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── settings │ │ │ │ │ ├── appearance │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── layout.tsx │ │ │ │ │ └── page.tsx │ │ │ ├── auth │ │ │ │ ├── (public) │ │ │ │ │ ├── forgot-password │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── login │ │ │ │ │ │ └── page.tsx │ │ │ │ │ └── register │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── actions │ │ │ │ │ └── index.ts │ │ │ │ ├── callback │ │ │ │ │ └── route.ts │ │ │ │ ├── layout.tsx │ │ │ │ ├── reset-password │ │ │ │ │ └── page.tsx │ │ │ │ └── welcome │ │ │ │ │ └── page.tsx │ │ │ ├── experimental │ │ │ │ └── page.tsx │ │ │ └── layout.tsx │ │ ├── components │ │ │ ├── form │ │ │ │ ├── AppForm.tsx │ │ │ │ ├── FormFieldset.tsx │ │ │ │ ├── FormInputField.tsx │ │ │ │ └── FormSelectField.tsx │ │ │ └── layouts │ │ │ │ ├── AppNavbar.tsx │ │ │ │ ├── Navbar.tsx │ │ │ │ ├── ThemeProvider.tsx │ │ │ │ └── ThemeToggle.tsx │ │ └── modules │ │ │ ├── auth │ │ │ ├── actions.ts │ │ │ ├── components │ │ │ │ ├── ForgotPasswordForm.tsx │ │ │ │ ├── LoginAuthForm.tsx │ │ │ │ ├── LoginWithEmailAndPasswordAuthForm.tsx │ │ │ │ ├── LoginWithEmailAuthForm.tsx │ │ │ │ ├── RegisterWithEmailAndPasswordAuthForm.tsx │ │ │ │ ├── ResetPasswordForm.tsx │ │ │ │ └── UpdateUserForm.tsx │ │ │ ├── styles │ │ │ │ └── auth.css │ │ │ └── validations │ │ │ │ ├── EmailFormSchema.ts │ │ │ │ ├── LoginWithEmailAndPasswordSchema.ts │ │ │ │ ├── RegisterWithEmailAndPasswordSchema.ts │ │ │ │ ├── ResetPasswordSchema.ts │ │ │ │ └── index.ts │ │ │ ├── dashboard │ │ │ └── components │ │ │ │ └── UserWelcomeCard.tsx │ │ │ ├── settings │ │ │ └── components │ │ │ │ ├── AppearanceForm.tsx │ │ │ │ └── SidebarNav.tsx │ │ │ └── user │ │ │ └── components │ │ │ └── ProfileIconMenu.tsx │ ├── supabase │ │ ├── .gitignore │ │ ├── config.toml │ │ ├── migrations │ │ │ └── 20240324185402_remote_schema.sql │ │ └── seed.sql │ ├── tailwind.config.js │ └── tsconfig.json └── docs │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── .storybook │ ├── main.js │ └── preview.jsx │ ├── package.json │ ├── postcss.config.cjs │ ├── stories │ ├── Mixins │ │ ├── colors.mdx │ │ ├── icons.mdx │ │ └── spacings.mdx │ ├── button.stories.tsx │ ├── dialog.stories.tsx │ ├── input.stories.tsx │ └── toast.stories.tsx │ ├── tailwind.config.js │ ├── tokens.ts │ └── tsconfig.json ├── package.json ├── packages ├── eslint-config-custom │ ├── README.md │ ├── library.js │ ├── next.js │ ├── package.json │ ├── react-internal.js │ └── storybook.js ├── tailwind-config │ ├── .eslintrc.js │ ├── package.json │ └── tailwind.config.js ├── tsconfig │ ├── base.json │ ├── nextjs.json │ ├── package.json │ └── react-library.json └── ui │ ├── .eslintrc.js │ ├── CHANGELOG.md │ ├── components.json │ ├── generate-tokens.js │ ├── index.tsx │ ├── package.json │ ├── src │ ├── components │ │ ├── magicui │ │ │ └── border-beam.tsx │ │ └── ui │ │ │ ├── button.tsx │ │ │ ├── card.tsx │ │ │ ├── dialog.tsx │ │ │ ├── dropdown-menu.tsx │ │ │ ├── form.tsx │ │ │ ├── icons.tsx │ │ │ ├── input.tsx │ │ │ ├── label.tsx │ │ │ ├── select.tsx │ │ │ ├── separator.tsx │ │ │ ├── skeleton.tsx │ │ │ ├── toast.tsx │ │ │ ├── toaster.tsx │ │ │ └── use-toast.ts │ └── lib │ │ └── utils.ts │ ├── styles │ └── globals.css │ ├── tailwind.config.js │ ├── tsconfig.json │ └── vite.config.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── public └── launchpad-logo-md.png ├── supabase ├── .gitignore ├── config.toml └── seed.sql ├── tsconfig.json └── turbo.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by 4 | `@changesets/cli`, a build tool that works with multi-package repos, or 5 | single-package repos to help you version and publish your code. You can find the 6 | full documentation for it 7 | [in our repository](https://github.com/changesets/changesets) 8 | 9 | We have a quick list of common questions to get you started engaging with this 10 | project in 11 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 12 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", 3 | "changelog": [ 4 | "@changesets/changelog-github", 5 | { "repo": "JadRizk/miniature-launchpad" } 6 | ], 7 | "commit": false, 8 | "fixed": [], 9 | "linked": [], 10 | "access": "restricted", 11 | "baseBranch": "main", 12 | "updateInternalDependencies": "patch", 13 | "ignore": [], 14 | "privatePackages": { 15 | "version": true, 16 | "tag": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/pull_request.yaml: -------------------------------------------------------------------------------- 1 | name: Pull Request 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | pull_request: 7 | runs-on: ubuntu-latest 8 | timeout-minutes: 15 9 | 10 | env: 11 | NEXT_APP_URL: test 12 | SUPABASE_URL: test 13 | SUPABASE_ANON_KEY: test 14 | 15 | steps: 16 | - name: ⬇️ Checkout Repo 17 | uses: actions/checkout@v4 18 | 19 | - name: 🥡 Install PNPM 20 | uses: pnpm/action-setup@v3 21 | with: 22 | version: 8 23 | 24 | - name: 🟢 Setup Node.js 20.x 25 | uses: actions/setup-node@v4 26 | with: 27 | node-version: 20 28 | cache: 'pnpm' 29 | 30 | - name: 🧩 Install Dependencies 31 | run: pnpm install 32 | 33 | - name: 🔍 Run Linting 34 | run: pnpm run lint 35 | 36 | - name: 📝 Run Formatting 37 | run: pnpm run format 38 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: 🚀 Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: ${{ github.workflow }}-${{ github.ref }} 9 | 10 | jobs: 11 | release: 12 | name: 🚀 Release 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: ⬇️ Checkout Repo 16 | uses: actions/checkout@v4 17 | 18 | - name: 🥡 Install PNPM 19 | uses: pnpm/action-setup@v3 20 | with: 21 | version: 8 22 | 23 | - name: 🟢 Setup Node.js 20.x 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: 20 27 | cache: 'pnpm' 28 | 29 | - name: 🧩 Install Dependencies 30 | run: pnpm install 31 | 32 | - name: 📣 Create Release Pull Request 33 | id: changesets 34 | uses: changesets/action@v1 35 | with: 36 | title: 'chore(release): version packages 🦋' 37 | publish: pnpm release 38 | version: pnpm version-packages 39 | commit: 'chore(release): version packages 🦋 [skip ci]' 40 | env: 41 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 42 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/webstorm,nextjs,node,turbo 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=webstorm,nextjs,node,turbo 3 | 4 | ### NextJS ### 5 | # dependencies 6 | /node_modules 7 | /.pnp 8 | .pnp.js 9 | 10 | # testing 11 | /coverage 12 | 13 | # next.js 14 | /.next/ 15 | /out/ 16 | 17 | # production 18 | /build 19 | 20 | # misc 21 | .DS_Store 22 | *.pem 23 | 24 | # debug 25 | npm-debug.log* 26 | yarn-debug.log* 27 | yarn-error.log* 28 | .pnpm-debug.log* 29 | 30 | # local env files 31 | .env*.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | # typescript 37 | *.tsbuildinfo 38 | next-env.d.ts 39 | 40 | ### Node ### 41 | # Logs 42 | logs 43 | *.log 44 | lerna-debug.log* 45 | 46 | # Diagnostic reports (https://nodejs.org/api/report.html) 47 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 48 | 49 | # Runtime data 50 | pids 51 | *.pid 52 | *.seed 53 | *.pid.lock 54 | 55 | # Directory for instrumented libs generated by jscoverage/JSCover 56 | lib-cov 57 | 58 | # Coverage directory used by tools like istanbul 59 | coverage 60 | *.lcov 61 | 62 | # nyc test coverage 63 | .nyc_output 64 | 65 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 66 | .grunt 67 | 68 | # Bower dependency directory (https://bower.io/) 69 | bower_components 70 | 71 | # node-waf configuration 72 | .lock-wscript 73 | 74 | # Compiled binary addons (https://nodejs.org/api/addons.html) 75 | build/Release 76 | 77 | # Dependency directories 78 | node_modules/ 79 | jspm_packages/ 80 | 81 | # Snowpack dependency directory (https://snowpack.dev/) 82 | web_modules/ 83 | 84 | # TypeScript cache 85 | 86 | # Optional npm cache directory 87 | .npm 88 | 89 | # Optional eslint cache 90 | .eslintcache 91 | 92 | # Optional stylelint cache 93 | .stylelintcache 94 | 95 | # Microbundle cache 96 | .rpt2_cache/ 97 | .rts2_cache_cjs/ 98 | .rts2_cache_es/ 99 | .rts2_cache_umd/ 100 | 101 | # Optional REPL history 102 | .node_repl_history 103 | 104 | # Output of 'npm pack' 105 | *.tgz 106 | 107 | # Yarn Integrity file 108 | .yarn-integrity 109 | 110 | # dotenv environment variable files 111 | .env 112 | .env.development.local 113 | .env.test.local 114 | .env.production.local 115 | .env.local 116 | 117 | # parcel-bundler cache (https://parceljs.org/) 118 | .cache 119 | .parcel-cache 120 | 121 | # Next.js build output 122 | .next 123 | out 124 | 125 | # Nuxt.js build / generate output 126 | .nuxt 127 | dist 128 | 129 | # Gatsby files 130 | .cache/ 131 | # Comment in the public line in if your project uses Gatsby and not Next.js 132 | # https://nextjs.org/blog/next-9-1#public-directory-support 133 | # public 134 | 135 | # vuepress build output 136 | .vuepress/dist 137 | 138 | # vuepress v2.x temp and cache directory 139 | .temp 140 | 141 | # Docusaurus cache and generated files 142 | .docusaurus 143 | 144 | # Serverless directories 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | .fusebox/ 149 | 150 | # DynamoDB Local files 151 | .dynamodb/ 152 | 153 | # TernJS port file 154 | .tern-port 155 | 156 | # Stores VSCode versions used for testing VSCode extensions 157 | .vscode-test 158 | 159 | # yarn v2 160 | .yarn/cache 161 | .yarn/unplugged 162 | .yarn/build-state.yml 163 | .yarn/install-state.gz 164 | .pnp.* 165 | 166 | ### Node Patch ### 167 | # Serverless Webpack directories 168 | .webpack/ 169 | 170 | # Optional stylelint cache 171 | 172 | # SvelteKit build / generate output 173 | .svelte-kit 174 | 175 | ### Turbo ### 176 | # Turborepo task cache 177 | .turbo 178 | 179 | ### WebStorm ### 180 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 181 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 182 | 183 | # User-specific stuff 184 | .idea/**/workspace.xml 185 | .idea/**/tasks.xml 186 | .idea/**/usage.statistics.xml 187 | .idea/**/dictionaries 188 | .idea/**/shelf 189 | 190 | # AWS User-specific 191 | .idea/**/aws.xml 192 | 193 | # Generated files 194 | .idea/**/contentModel.xml 195 | 196 | # Sensitive or high-churn files 197 | .idea/**/dataSources/ 198 | .idea/**/dataSources.ids 199 | .idea/**/dataSources.local.xml 200 | .idea/**/sqlDataSources.xml 201 | .idea/**/dynamic.xml 202 | .idea/**/uiDesigner.xml 203 | .idea/**/dbnavigator.xml 204 | 205 | # Gradle 206 | .idea/**/gradle.xml 207 | .idea/**/libraries 208 | 209 | # Gradle and Maven with auto-import 210 | # When using Gradle or Maven with auto-import, you should exclude module files, 211 | # since they will be recreated, and may cause churn. Uncomment if using 212 | # auto-import. 213 | # .idea/artifacts 214 | # .idea/compiler.xml 215 | # .idea/jarRepositories.xml 216 | # .idea/modules.xml 217 | # .idea/*.iml 218 | # .idea/modules 219 | # *.iml 220 | # *.ipr 221 | 222 | # CMake 223 | cmake-build-*/ 224 | 225 | # Mongo Explorer plugin 226 | .idea/**/mongoSettings.xml 227 | 228 | # File-based project format 229 | *.iws 230 | 231 | # IntelliJ 232 | out/ 233 | 234 | # mpeltonen/sbt-idea plugin 235 | .idea_modules/ 236 | 237 | # JIRA plugin 238 | atlassian-ide-plugin.xml 239 | 240 | # Cursive Clojure plugin 241 | .idea/replstate.xml 242 | 243 | # SonarLint plugin 244 | .idea/sonarlint/ 245 | 246 | # Crashlytics plugin (for Android Studio and IntelliJ) 247 | com_crashlytics_export_strings.xml 248 | crashlytics.properties 249 | crashlytics-build.properties 250 | fabric.properties 251 | 252 | # Editor-based Rest Client 253 | .idea/httpRequests 254 | 255 | # Android studio 3.1+ serialized cache file 256 | .idea/caches/build_file_checksums.ser 257 | 258 | ### WebStorm Patch ### 259 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 260 | 261 | # *.iml 262 | # modules.xml 263 | # .idea/misc.xml 264 | # *.ipr 265 | .idea 266 | 267 | # Sonarlint plugin 268 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 269 | .idea/**/sonarlint/ 270 | 271 | # SonarQube Plugin 272 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 273 | .idea/**/sonarIssues.xml 274 | 275 | # Markdown Navigator plugin 276 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 277 | .idea/**/markdown-navigator.xml 278 | .idea/**/markdown-navigator-enh.xml 279 | .idea/**/markdown-navigator/ 280 | 281 | # Cache file creation bug 282 | # See https://youtrack.jetbrains.com/issue/JBR-2257 283 | .idea/$CACHE_FILE$ 284 | 285 | # CodeStream plugin 286 | # https://plugins.jetbrains.com/plugin/12206-codestream 287 | .idea/codestream.xml 288 | 289 | # Azure Toolkit for IntelliJ plugin 290 | # https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij 291 | .idea/**/azureSettings.xml 292 | 293 | # End of https://www.toptal.com/developers/gitignore/api/webstorm,nextjs,node,turbo -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | pnpm exec lint-staged -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/mudd-app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | auto-install-peers = true 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": true, 4 | "htmlWhitespaceSensitivity": "css", 5 | "insertPragma": false, 6 | "jsxBracketSameLine": false, 7 | "jsxSingleQuote": true, 8 | "printWidth": 80, 9 | "proseWrap": "always", 10 | "quoteProps": "as-needed", 11 | "requirePragma": false, 12 | "semi": true, 13 | "singleQuote": true, 14 | "tabWidth": 2, 15 | "trailingComma": "all", 16 | "useTabs": false 17 | } 18 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["denoland.vscode-deno"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "deno.enablePaths": ["supabase/functions"], 3 | "deno.lint": true, 4 | "deno.unstable": true, 5 | "[typescript]": { 6 | "editor.defaultFormatter": "denoland.vscode-deno" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Your Image Description 3 |

4 | 5 | # Launchpad 6 | 7 | ![Turborepo Badge](https://img.shields.io/badge/Turborepo-EF4444?logo=turborepo&logoColor=fff&style=flat) 8 | ![Tailwind CSS Badge](https://img.shields.io/badge/Tailwind%20CSS-06B6D4?logo=tailwindcss&logoColor=fff&style=flat) 9 | ![TypeScript Badge](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=fff&style=flat) 10 | ![Next.js](https://img.shields.io/badge/Next.js-black?logo=next.js&logoColor=white) 11 | ![Supabase](https://img.shields.io/badge/Supabase-3FCF8E?logo=supabase&logoColor=fff) 12 | ![Storybook](https://img.shields.io/badge/Storybook-FF4785?logo=storybook&logoColor=fff) 13 | ![shadcn/ui](https://img.shields.io/badge/shadcn%2Fui-000?logo=shadcnui&logoColor=fff) 14 | ![ESLint Badge](https://img.shields.io/badge/ESLint-4B32C3?logo=eslint&logoColor=fff&style=flat) 15 | ![Prettier Badge](https://img.shields.io/badge/Prettier-F7B93E?logo=prettier&logoColor=fff&style=flat) 16 | ![pnpm](https://img.shields.io/badge/pnpm-F69220?logo=pnpm&logoColor=fff) 17 | ![GitHub Actions](https://img.shields.io/badge/GitHub_Actions-2088FF?logo=github-actions&logoColor=white) 18 | ![Vercel](https://img.shields.io/badge/Vercel-%23000000.svg?logo=vercel&logoColor=white) 19 | 20 | --- 21 | 22 | Welcome to **Launchpad**, a turbocharged monorepo equipped with a Next.js 14 23 | application, a comprehensive Storybook-hosted component library, and essential 24 | configuration packages for ESLint, Tailwind CSS, and TypeScript. Designed to 25 | streamline the development of scalable and secure web applications, 26 | **Launchpad** offers a robust suite of tools and a customizable UI component 27 | library to enhance your development workflow. 28 | 29 | - [Launchpad](#launchpad) 30 | - [🚀 Getting Started](#-getting-started) 31 | - [Installation](#installation) 32 | - [Environment Setup](#environment-setup) 33 | - [Useful Commands](#useful-commands) 34 | - [📦 Apps \& Packages](#-apps--packages) 35 | - [🛠 Tools Powering This Repository](#-tools-powering-this-repository) 36 | - [🧑‍💻 Setting Up Supabase Locally](#-setting-up-supabase-locally) 37 | - [Prerequisites](#prerequisites) 38 | - [Installation](#installation-1) 39 | - [Configuration](#configuration) 40 | - [Useful Commands](#useful-commands-1) 41 | - [🧱 Components](#-components) 42 | - [🔄 Versioning \& Publishing Packages](#-versioning--publishing-packages) 43 | - [🔧 Generating Changesets](#-generating-changesets) 44 | - [📚 Further Documentation and Resources](#-further-documentation-and-resources) 45 | 46 | ## 🚀 Getting Started 47 | 48 | To get started ensure you have the necessary tools installed -PNPM & Node 49 | (v21+)-, and then clone this repository: 50 | 51 | ### Installation 52 | 53 | ```sh 54 | # Clone repo locally 55 | git clone https://github.com/JadRizk/miniature-launchpad.git 56 | cd miniature-launchpad 57 | 58 | # Install dependencies 59 | pnpm install 60 | ``` 61 | 62 | ### Environment Setup 63 | 64 | Before you start the application, you must configure the environment variables 65 | for Supabase authentication and Umami analytics. Create a .env.local file at the 66 | root of your project and include the following: 67 | 68 | ```sh 69 | SUPABASE_URL=your_supabase_url 70 | SUPABASE_ANON_KEY=your_supabase_anon_key 71 | 72 | UMAMI_SCRIPT_URL=your_umami_script_url 73 | ``` 74 | 75 | For more information on setting up Supabase, visit the 76 | [Supabase Documentation](https://supabase.com/). 77 | 78 | ### Useful Commands 79 | 80 | - `pnpm build` - Build all packages, including the Storybook site 81 | - `pnpm dev` - Run all packages locally and preview with Storybook 82 | - `pnpm lint` - Lint all packages 83 | - `pnpm changeset` - Generate a changeset 84 | - `pnpm clean` - Clean up all `node_modules` and `dist` folders (runs each 85 | package's clean script) 86 | 87 | ## 📦 Apps & Packages 88 | 89 | Launchpad's Turborepo structure is designed to maximize modularity and 90 | efficiency across multiple projects. Each app and package is tailored to 91 | specific aspects of development, ensuring a cohesive and scalable ecosystem: 92 | 93 | - **`apps/app`**: Our main Next.js 14 application, serving as the face of your 94 | digital presence. It integrates Supabase for robust authentication and 95 | leverages our unified component library to ensure a seamless user experience. 96 | - **`apps/docs`**: A dedicated Storybook-powered site for documenting and 97 | showcasing UI components. It offers an interactive platform for developers to 98 | view and test component designs in isolation. 99 | - **`packages/ui`**: The core of our UI development, this package includes 100 | reusable React components that ensure consistency and quality across all 101 | applications and projects within the repository. 102 | - **`packages/tailwind-config`**: Provides a centralized Tailwind CSS 103 | configuration to maintain a uniform styling framework throughout all our 104 | applications and components. 105 | - **`packages/typescript-config`**: Manages shared TypeScript configurations, 106 | facilitating consistent coding practices and error-free compilation across the 107 | monorepo. 108 | - **`packages/eslint-config`**: Delivers a pre-set ESLint configuration designed 109 | to enforce stringent code quality and style guidelines for all JavaScript and 110 | TypeScript codebases. 111 | 112 | ## 🛠 Tools Powering This Repository 113 | 114 | Launchpad leverages a suite of top-tier development tools designed to enhance 115 | productivity and maintain high standards across the development lifecycle: 116 | 117 | - 🏎 [**Turborepo**](https://turbo.build/repo) — A high-performance build system 118 | tailored for efficient management of monorepos. 119 | - 🚀 [**Next.js 14**](https://nextjs.org/) — A React framework for building 120 | user-friendly and scalable web applications. 121 | - 🔐 [**Supabase Authentication**](https://supabase.com/auth) — Provides robust 122 | authentication solutions, enabling secure and scalable user management. 123 | - 📖 [**Storybook**](https://storybook.js.org/) — A sandboxed environment for 124 | developing and isolating UI components, powered by Vite for near-instant 125 | feedback. 126 | - 🔠 [**TypeScript**](https://www.typescriptlang.org/) — Enhances JavaScript 127 | with static types to improve predictability and maintainability of code. 128 | - 🌊 [**Tailwind CSS**](https://tailwindcss.com/) — A utility-first CSS 129 | framework for rapidly building custom designs. 130 | - 🌐 [**Shadcn**](https://github.com/shadcn) — A modern toolchain for front-end 131 | development, focusing on performance and developer experience. 132 | - 🔍 [**ESLint**](https://eslint.org/) — A linter tool to identify and fix 133 | problems in JavaScript and TypeScript code, enforcing code quality standards. 134 | - ✨ [**Prettier**](https://prettier.io) — An opinionated code formatter that 135 | ensures consistency in code style. 136 | - 🏷️ [**Changesets**](https://github.com/changesets/changesets) — Manages 137 | versioning and changelog generation, streamlining the release process. 138 | - ⚙️ [**GitHub Actions**](https://github.com/features/actions) — Automates 139 | workflows for continuous integration and deployment, enhancing development 140 | pipelines. 141 | - 📊 [**Umami Analytics**](https://umami.is/) — A simple, privacy-focused 142 | alternative to Google Analytics, providing insights into user interactions 143 | without compromising privacy. 144 | 145 | **Note**: Each package and app is 100% 146 | [TypeScript](https://www.typescriptlang.org/). Workspaces enables us to "hoist" 147 | dependencies that are shared between packages to the root `package.json`. This 148 | means smaller `node_modules` folders and a better local dev experience. To 149 | install a dependency for the entire monorepo, use the `-w` workspaces flag with 150 | `pnpm add`. 151 | 152 | ## 🧑‍💻 Setting Up Supabase Locally 153 | 154 | Setting up Supabase locally can significantly streamline your development 155 | workflow. Follow these steps to get started with Supabase CLI for local 156 | development: 157 | 158 | ### Prerequisites 159 | 160 | Ensure you have Docker installed on your machine, as Supabase relies on Docker 161 | containers to run the local development environment. 162 | 163 | ### Installation 164 | 165 | 1. **Install Supabase CLI**: First, install the Supabase CLI by running the 166 | following command: 167 | 168 | ```sh 169 | # Install Supabase CLI 170 | npm install -g supabase 171 | ``` 172 | 173 | 2. **Start Supabase**: Navigate to your project's root directory and initialize 174 | Supabase: 175 | 176 | ```sh 177 | # Initialize Supabase in your project 178 | supabase init 179 | ``` 180 | 181 | 3. **Start the Supabase local development environment**: Run the following 182 | command to start the local Supabase environment: 183 | 184 | ```sh 185 | # Start Supabase local environment 186 | supabase start 187 | ``` 188 | 189 | This command will spin up the necessary Docker containers for Supabase, 190 | including the database, authentication, and storage services. 191 | 192 | ### Configuration 193 | 194 | 1. **Configure Environment Variables**: Update your `.env.local` file to use the 195 | local Supabase instance. Replace `your_supabase_url` and 196 | `your_supabase_anon_key` with the values provided by the local Supabase 197 | environment: 198 | 199 | ```sh 200 | NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321 201 | NEXT_PUBLIC_SUPABASE_ANON_KEY=your_local_anon_key 202 | ``` 203 | 204 | 2. **Migrate Database**: To apply database migrations, use the following 205 | command: 206 | 207 | ```sh 208 | # Apply database migrations 209 | supabase db push 210 | ``` 211 | 212 | This command ensures your local database schema matches your project 213 | requirements. 214 | 215 | ### Useful Commands 216 | 217 | - `supabase start` - Start the local Supabase development environment. 218 | - `supabase stop` - Stop the local Supabase environment. 219 | - `supabase db push` - Apply database migrations. 220 | - `supabase db reset` - Reset the local database to its initial state. 221 | 222 | For more detailed information on setting up and using Supabase locally, visit 223 | the 224 | [Supabase CLI Local Development Guide](https://supabase.com/docs/guides/cli/local-development). 225 | 226 | ## 🧱 Components 227 | 228 | Each file inside of `packages/src/components` is a component inside our design 229 | system. For example: 230 | 231 | ```tsx:acme-core/src/Button.tsx 232 | import * as React from 'react'; 233 | 234 | export interface ButtonProps { 235 | children: React.ReactNode; 236 | } 237 | 238 | export function Button(props: ButtonProps) { 239 | return ; 240 | } 241 | 242 | Button.displayName = 'Button'; 243 | ``` 244 | 245 | When adding a new file, ensure the component is also exported from the entry 246 | `index.tsx` file: 247 | 248 | ```tsx:packages/src/components/index.tsx 249 | export * from './Button'; 250 | ``` 251 | 252 | ## 🔄 Versioning & Publishing Packages 253 | 254 | The project uses [Changesets](https://github.com/changesets/changesets) for 255 | version management, changelog generation, and npm publishing. The workflow is 256 | designed to automate and streamline the release process, ensuring reliable and 257 | consistent package updates. 258 | 259 | ### 🔧 Generating Changesets 260 | 261 | When you make changes that should be tracked in the changelog, follow these 262 | steps: 263 | 264 | 1. **Start the Changeset**: Run the following command in your terminal: 265 | `pnpm changeset` 266 | 2. **Select Packages**: The CLI will prompt you to select the packages affected 267 | by your changes. Ensure you create one changeset per repository to keep the 268 | changelogs separate. 269 | 3. **Version Bumps**: Decide on the version bump for the selected packages. It's 270 | crucial to follow semantic versioning best practices. 271 | 4. **Summarize Changes**: Write a clear summary of what changes have been made; 272 | this summary will be included in the changelog. 273 | 5. **Review and Confirm**: Confirm the details of your changeset. A Markdown 274 | file will then be created in the changeset folder, listing the packages and 275 | summarizing the changes. 276 | 277 | ## 📚 Further Documentation and Resources 278 | 279 | To help you maximize your use of **Launchpad**, here are some valuable resources 280 | and documentation links: 281 | 282 | - [Next.js Documentation](https://nextjs.org/docs) - Learn about Next.js 283 | features and API. 284 | - [Supabase Documentation](https://supabase.com/docs) - Comprehensive guides and 285 | API references for using Supabase for authentication and database services. 286 | - [Storybook Documentation](https://storybook.js.org/docs) - Explore Storybook 287 | to better understand how to build and test UI components in isolation. 288 | - [Tailwind CSS Documentation](https://tailwindcss.com/docs) - Get to know how 289 | to style your applications efficiently using Tailwind CSS. 290 | - [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html) - 291 | Deepen your knowledge of TypeScript and how to use it effectively in your 292 | projects. 293 | - [ESLint User Guide](https://eslint.org/docs/user-guide) - Configure ESLint to 294 | enforce code quality standards in your JavaScript and TypeScript code. 295 | - [Prettier Documentation](https://prettier.io/docs/en/index.html) - Learn how 296 | to use Prettier for automatic code formatting. 297 | - [Turborepo Guide](https://turborepo.org/docs) - Understand how to use 298 | Turborepo to manage your monorepo efficiently. 299 | 300 | These resources provide extensive information and best practices that can boost 301 | your development process and enhance your understanding of the technologies 302 | integrated into **Launchpad**. 303 | 304 | --- 305 | -------------------------------------------------------------------------------- /apps/app/.env.local.example: -------------------------------------------------------------------------------- 1 | NEXT_APP_URL=your-app-url 2 | 3 | # Supabase 4 | SUPABASE_URL=your-project-url 5 | SUPABASE_ANON_KEY=your-anon-key 6 | 7 | #Umami 8 | UMAMI_WEBSITE_ID=your-website-id 9 | 10 | -------------------------------------------------------------------------------- /apps/app/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ["custom/next"], 3 | }; 4 | -------------------------------------------------------------------------------- /apps/app/.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 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | ./supabase 39 | -------------------------------------------------------------------------------- /apps/app/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # app 2 | 3 | ## 0.0.3 4 | 5 | ### Patch Changes 6 | 7 | - [`f577fdc`](https://github.com/JadRizk/turborepo-launchpad/commit/f577fdcd5ab04413456ae1885cce8c0577a0a6e3) 8 | Thanks [@JadRizk](https://github.com/JadRizk)! - Refactor landing page 9 | 10 | - Updated dependencies 11 | [[`f577fdc`](https://github.com/JadRizk/turborepo-launchpad/commit/f577fdcd5ab04413456ae1885cce8c0577a0a6e3)]: 12 | - ui@0.0.2 13 | 14 | ## 0.0.2 15 | 16 | ### Patch Changes 17 | 18 | - [#19](https://github.com/JadRizk/turborepo-launchpad/pull/19) 19 | [`547690f`](https://github.com/JadRizk/turborepo-launchpad/commit/547690f3ad58252028fc8129c20a75f2d197f388) 20 | Thanks [@JadRizk](https://github.com/JadRizk)! - Fix local authentication 21 | issue 22 | 23 | ## 0.0.1 24 | 25 | ### Patch Changes 26 | 27 | - [#13](https://github.com/JadRizk/miniature-launchpad/pull/13) 28 | [`2290e14`](https://github.com/JadRizk/miniature-launchpad/commit/2290e14ede8fbaa169a61282934da798064c0bfe) 29 | Thanks [@JadRizk](https://github.com/JadRizk)! - 🚀 Initial Log 30 | 31 | - Updated dependencies 32 | [[`2290e14`](https://github.com/JadRizk/miniature-launchpad/commit/2290e14ede8fbaa169a61282934da798064c0bfe)]: 33 | - ui@0.0.1 34 | -------------------------------------------------------------------------------- /apps/app/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with 2 | [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 3 | 4 | ## Getting Started 5 | 6 | First, run the development server: 7 | 8 | ```bash 9 | npm run dev 10 | # or 11 | yarn dev 12 | # or 13 | pnpm dev 14 | # or 15 | bun dev 16 | ``` 17 | 18 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the 19 | result. 20 | 21 | You can start editing the page by modifying `app/page.tsx`. The page 22 | auto-updates as you edit the file. 23 | 24 | This project uses 25 | [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to 26 | automatically optimize and load Inter, a custom Google Font. 27 | 28 | ## Learn More 29 | 30 | To learn more about Next.js, take a look at the following resources: 31 | 32 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js 33 | features and API. 34 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 35 | 36 | You can check out 37 | [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your 38 | feedback and contributions are welcome! 39 | 40 | ## Deploy on Vercel 41 | 42 | The easiest way to deploy your Next.js app is to use the 43 | [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) 44 | from the creators of Next.js. 45 | 46 | Check out our 47 | [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more 48 | details. 49 | -------------------------------------------------------------------------------- /apps/app/lib/supabase/server.ts: -------------------------------------------------------------------------------- 1 | 'use server'; 2 | 3 | import { cookies } from 'next/headers'; 4 | import type { CookieOptions } from '@supabase/ssr'; 5 | import { createServerClient } from '@supabase/ssr'; 6 | 7 | async function createSupabaseServerClient() { 8 | const cookieStore = cookies(); 9 | return createServerClient( 10 | process.env.SUPABASE_URL!, 11 | process.env.SUPABASE_ANON_KEY!, 12 | { 13 | cookies: { 14 | get(name: string) { 15 | return cookieStore.get(name)?.value; 16 | }, 17 | set(name: string, value: string, options: CookieOptions) { 18 | cookieStore.set({ name, value, ...options }); 19 | }, 20 | remove(name: string, options: CookieOptions) { 21 | cookieStore.set({ name, ...options }); 22 | }, 23 | }, 24 | }, 25 | ); 26 | } 27 | 28 | export default createSupabaseServerClient; 29 | -------------------------------------------------------------------------------- /apps/app/middleware.ts: -------------------------------------------------------------------------------- 1 | import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs'; 2 | import type { NextRequest } from 'next/server'; 3 | import { NextResponse } from 'next/server'; 4 | 5 | export async function middleware(req: NextRequest) { 6 | const res = NextResponse.next(); 7 | 8 | const supabase = createMiddlewareClient({ req, res }); 9 | 10 | await supabase.auth.getSession(); 11 | 12 | return res; 13 | } 14 | -------------------------------------------------------------------------------- /apps/app/next.config.js: -------------------------------------------------------------------------------- 1 | const getEnv = key => { 2 | const value = process.env[key]; 3 | if (!value) throw Error(`Missing environment variable: ${key}`); 4 | return value; 5 | }; 6 | 7 | // TODO: refactor to use the exported envs. Used now as a check 8 | module.exports = { 9 | reactStrictMode: true, 10 | transpilePackages: ['ui', 'tailwind-config'], 11 | experimental: { 12 | typedRoutes: true, 13 | }, 14 | publicRuntimeConfig: { 15 | appUrl: getEnv('NEXT_APP_URL'), 16 | supaBaseUrl: getEnv('SUPABASE_URL'), 17 | supaKey: getEnv('SUPABASE_ANON_KEY'), 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /apps/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "0.0.3", 4 | "private": false, 5 | "scripts": { 6 | "dev": "NODE_OPTIONS='--inspect' next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@hookform/error-message": "^2.0.1", 13 | "@hookform/resolvers": "^3.3.4", 14 | "@next/eslint-plugin-next": "^12.3.0", 15 | "@radix-ui/react-toast": "^1.1.5", 16 | "@supabase/auth-helpers-nextjs": "^0.8.7", 17 | "@supabase/ssr": "^0.0.10", 18 | "@supabase/supabase-js": "^2.38.5", 19 | "next": "14.0.3", 20 | "next-themes": "^0.2.1", 21 | "react": "^18", 22 | "react-confetti": "^6.1.0", 23 | "react-dom": "^18", 24 | "react-hook-form": "^7.48.2", 25 | "ui": "workspace:*", 26 | "zod": "^3.22.4" 27 | }, 28 | "devDependencies": { 29 | "@types/node": "^20", 30 | "@types/react": "^18", 31 | "@types/react-dom": "^18", 32 | "autoprefixer": "^10.0.1", 33 | "date-fns": "^4.1.0", 34 | "eslint-config-custom": "workspace:*", 35 | "postcss": "^8", 36 | "tailwind-config": "workspace:*", 37 | "tailwindcss": "^3.3.0", 38 | "tsconfig": "workspace:*", 39 | "typescript": "^5" 40 | }, 41 | "packageManager": "pnpm@9.1.1" 42 | } 43 | -------------------------------------------------------------------------------- /apps/app/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /apps/app/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JadRizk/turborepo-launchpad/cacd6cb5565725e47a593c9fc609c31d137d7f15/apps/app/public/apple-touch-icon.png -------------------------------------------------------------------------------- /apps/app/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JadRizk/turborepo-launchpad/cacd6cb5565725e47a593c9fc609c31d137d7f15/apps/app/public/favicon-16x16.png -------------------------------------------------------------------------------- /apps/app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JadRizk/turborepo-launchpad/cacd6cb5565725e47a593c9fc609c31d137d7f15/apps/app/public/favicon.ico -------------------------------------------------------------------------------- /apps/app/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/app/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/app/src/app/(splash)/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | import { redirect } from 'next/navigation'; 3 | import { NavBar } from '../../components/layouts/Navbar'; 4 | import { ThemeToggle } from '../../components/layouts/ThemeToggle'; 5 | import { getCurrentUser } from '../app/actions/user'; 6 | 7 | const LandingLayout = async ({ children }: { children: ReactNode }) => { 8 | const user = await getCurrentUser(); 9 | 10 | if (user) return redirect('/app'); 11 | return ( 12 |
13 |
14 | 15 |
16 |
{children}
17 | 25 |
26 | ); 27 | }; 28 | 29 | export default LandingLayout; 30 | -------------------------------------------------------------------------------- /apps/app/src/app/(splash)/page.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from 'next'; 2 | import Link from 'next/link'; 3 | import { buttonVariants, cn } from 'ui'; 4 | 5 | const Page: NextPage = () => { 6 | return ( 7 |
8 |
9 |

10 | Build Faster. Scale Smarter. 11 |

12 |

13 | Launchpad is the monorepo framework designed for speed, power, and 14 | flexibility—so you can focus on what matters. 15 |

16 | 20 | Get Started 21 | 22 |
23 |
24 | ); 25 | }; 26 | 27 | export default Page; 28 | -------------------------------------------------------------------------------- /apps/app/src/app/app/actions/user.ts: -------------------------------------------------------------------------------- 1 | 'use server'; 2 | 3 | import createSupabaseServerClient from '../../../../lib/supabase/server'; 4 | 5 | export async function getCurrentUser() { 6 | const supabase = await createSupabaseServerClient(); 7 | 8 | const { data } = await supabase.auth.getSession(); 9 | 10 | return data.session?.user; 11 | } 12 | 13 | export async function signOut() { 14 | const supabase = await createSupabaseServerClient(); 15 | 16 | await supabase.auth.signOut(); 17 | } 18 | -------------------------------------------------------------------------------- /apps/app/src/app/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | import { redirect } from 'next/navigation'; 3 | import { AppNavBar } from '../../components/layouts/AppNavbar'; 4 | import { getCurrentUser } from './actions/user'; 5 | 6 | const AppLayout = async ({ children }: { children: ReactNode }) => { 7 | const user = await getCurrentUser(); 8 | 9 | if (!user) return redirect('/auth/login'); 10 | 11 | return ( 12 |
13 |
14 | 15 |
16 |
17 |
18 |
{children}
19 |
20 |
21 |
22 | ); 23 | }; 24 | 25 | export default AppLayout; 26 | -------------------------------------------------------------------------------- /apps/app/src/app/app/page.tsx: -------------------------------------------------------------------------------- 1 | import { Suspense } from 'react'; 2 | import { UserWelcomeCard } from '../../modules/dashboard/components/UserWelcomeCard'; 3 | import { getCurrentUser } from './actions/user'; 4 | import { Skeleton } from 'ui'; 5 | 6 | const Page = async () => { 7 | const user = await getCurrentUser(); 8 | 9 | return ( 10 |
11 |
12 | }> 13 | 14 | 15 |
16 |
17 | ); 18 | }; 19 | 20 | export default Page; 21 | -------------------------------------------------------------------------------- /apps/app/src/app/app/settings/appearance/page.tsx: -------------------------------------------------------------------------------- 1 | import type { FC } from 'react'; 2 | import { Separator } from 'ui/src/components/ui/separator'; 3 | import { AppearanceForm } from '../../../../modules/settings/components/AppearanceForm'; 4 | 5 | const AppearancePage: FC = () => { 6 | return ( 7 |
8 |
9 |

Appearance

10 |

11 | Customize the appearance of the app. Automatically switch between day 12 | and night themes. 13 |

14 |
15 | 16 | 17 |
18 | ); 19 | }; 20 | 21 | export default AppearancePage; 22 | -------------------------------------------------------------------------------- /apps/app/src/app/app/settings/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | import { Separator } from 'ui/src/components/ui/separator'; 3 | import { SidebarNav } from '../../../modules/settings/components/SidebarNav'; 4 | 5 | const sidebarNavItems = [ 6 | { 7 | title: 'Profile', 8 | href: '/app/settings', 9 | }, 10 | { 11 | title: 'Appearance', 12 | href: '/app/settings/appearance', 13 | }, 14 | ]; 15 | 16 | const SettingsLayout = async ({ children }: { children: ReactNode }) => { 17 | return ( 18 |
19 |
20 |

Settings

21 |

22 | Manage your account settings and set e-mail preferences. 23 |

24 |
25 | 26 |
27 | 30 |
{children}
31 |
32 |
33 | ); 34 | }; 35 | 36 | export default SettingsLayout; 37 | -------------------------------------------------------------------------------- /apps/app/src/app/app/settings/page.tsx: -------------------------------------------------------------------------------- 1 | import { Separator } from 'ui/src/components/ui/separator'; 2 | import { UpdateUserForm } from '../../../modules/auth/components/UpdateUserForm'; 3 | import { getCurrentUser } from '../actions/user'; 4 | 5 | const SettingsPage = async () => { 6 | const user = await getCurrentUser(); 7 | 8 | return ( 9 |
10 |
11 |

Profile

12 |

13 | This is how others will see you on the site. 14 |

15 |
16 | 17 | 18 |
19 | ); 20 | }; 21 | 22 | export default SettingsPage; 23 | -------------------------------------------------------------------------------- /apps/app/src/app/auth/(public)/forgot-password/page.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from 'next'; 2 | import Link from 'next/link'; 3 | import { Icons } from 'ui'; 4 | import { ForgotPasswordForm } from '../../../../modules/auth/components/ForgotPasswordForm'; 5 | 6 | const Page: NextPage = () => { 7 | return ( 8 |
9 |
10 | 11 |

12 | Forgot Your Password? 13 |

14 |

15 | No worries! Enter your email below to reset your password. 16 |

17 |
18 | 19 |

20 | Remembered your password?{' '} 21 | 25 | Sign in here 26 | 27 |

28 |
29 | ); 30 | }; 31 | 32 | export default Page; 33 | -------------------------------------------------------------------------------- /apps/app/src/app/auth/(public)/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | import React from 'react'; 3 | import { redirect } from 'next/navigation'; 4 | import { getCurrentUser } from '../../app/actions/user'; 5 | 6 | const PublicAuthLayout = async ({ children }: { children: ReactNode }) => { 7 | const user = await getCurrentUser(); 8 | 9 | if (user) return redirect('/app'); 10 | 11 | return <> {children} ; 12 | }; 13 | 14 | export default PublicAuthLayout; 15 | -------------------------------------------------------------------------------- /apps/app/src/app/auth/(public)/login/page.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from 'next'; 2 | import Link from 'next/link'; 3 | import { Icons } from 'ui'; 4 | import { LoginAuthForm } from '../../../../modules/auth/components/LoginAuthForm'; 5 | 6 | const Page: NextPage = () => { 7 | return ( 8 |
9 |
10 | 11 |

Welcome back

12 |

13 | Enter your email to sign in to your account 14 |

15 |
16 | 17 |

18 | 22 | Don't have an account? Sign Up 23 | 24 |

25 |
26 | ); 27 | }; 28 | 29 | export default Page; 30 | -------------------------------------------------------------------------------- /apps/app/src/app/auth/(public)/register/page.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from 'next'; 2 | import Link from 'next/link'; 3 | import { Icons } from 'ui'; 4 | import { RegisterWithEmailAndPasswordAuthForm } from '../../../../modules/auth/components/RegisterWithEmailAndPasswordAuthForm'; 5 | 6 | const Page: NextPage = () => { 7 | return ( 8 |
9 |
10 | 11 |

Register now!

12 |

13 | Enter your email to sign in to your account 14 |

15 |
16 | 17 |

18 | 22 | Have an account? Sign In 23 | 24 |

25 |
26 | ); 27 | }; 28 | 29 | export default Page; 30 | -------------------------------------------------------------------------------- /apps/app/src/app/auth/actions/index.ts: -------------------------------------------------------------------------------- 1 | 'use server'; 2 | 3 | import createSupabaseServerClient from '../../../../lib/supabase/server'; 4 | 5 | export async function signUpWithEmailAndPassword(values: { 6 | email: string; 7 | password: string; 8 | }) { 9 | const supabase = await createSupabaseServerClient(); 10 | 11 | const { data, error } = await supabase.auth.signUp({ 12 | email: values.email, 13 | password: values.password, 14 | options: { 15 | emailRedirectTo: `${process.env.NEXT_APP_URL!}/auth/callback`, 16 | }, 17 | }); 18 | 19 | return { data, error }; 20 | } 21 | 22 | export async function signInWithEmailAndPassword(values: { 23 | email: string; 24 | password: string; 25 | }) { 26 | const supabase = await createSupabaseServerClient(); 27 | 28 | return supabase.auth.signInWithPassword(values); 29 | } 30 | 31 | export const signInWithRecoveryToken = async (code: string) => { 32 | const supabase = await createSupabaseServerClient(); 33 | 34 | return supabase.auth.exchangeCodeForSession(code); 35 | }; 36 | 37 | export async function signInWithEmail(email: string) { 38 | const supabase = await createSupabaseServerClient(); 39 | 40 | // signup users if not available 41 | return supabase.auth.signInWithOtp({ 42 | email, 43 | options: { 44 | emailRedirectTo: `${process.env.NEXT_APP_URL!}/auth/welcome`, 45 | }, 46 | }); 47 | } 48 | 49 | // Todo: Add loginWithGithub 50 | 51 | export async function resetPasswordForEmail(email: string) { 52 | const supabase = await createSupabaseServerClient(); 53 | 54 | return supabase.auth.resetPasswordForEmail(email, { 55 | redirectTo: `${process.env.NEXT_APP_URL!}/auth/reset-password`, 56 | }); 57 | } 58 | 59 | export async function updatePassword(password: string) { 60 | const supabase = await createSupabaseServerClient(); 61 | 62 | return supabase.auth.updateUser({ 63 | password, 64 | }); 65 | } 66 | -------------------------------------------------------------------------------- /apps/app/src/app/auth/callback/route.ts: -------------------------------------------------------------------------------- 1 | import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'; 2 | import { cookies } from 'next/headers'; 3 | import { NextResponse } from 'next/server'; 4 | import type { NextRequest } from 'next/server'; 5 | 6 | export async function GET(request: NextRequest) { 7 | const requestUrl = new URL(request.url); 8 | const code = requestUrl.searchParams.get('code'); 9 | 10 | if (code) { 11 | const cookieStore = cookies(); 12 | const supabase = createRouteHandlerClient({ 13 | cookies: () => cookieStore, 14 | }); 15 | await supabase.auth.exchangeCodeForSession(code); 16 | } 17 | 18 | // URL to redirect to after sign in process completes 19 | return NextResponse.redirect( 20 | process.env.NEXT_APP_URL ?? `http://localhost:3000/`, 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /apps/app/src/app/auth/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | import React, { Suspense } from 'react'; 3 | import Link from 'next/link'; 4 | import { buttonVariants, cn, Icons } from 'ui'; 5 | 6 | const AuthLayout = async ({ children }: { children: ReactNode }) => { 7 | return ( 8 |
9 | 16 | 17 | 18 | 19 | 20 |
{children}
21 |
22 |
23 | ); 24 | }; 25 | 26 | export default AuthLayout; 27 | -------------------------------------------------------------------------------- /apps/app/src/app/auth/reset-password/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import type { NextPage } from 'next'; 4 | import { Icons, toast } from 'ui'; 5 | import { useRouter, useSearchParams } from 'next/navigation'; 6 | import { useEffect } from 'react'; 7 | import { ResetPasswordForm } from '../../../modules/auth/components/ResetPasswordForm'; 8 | import { signInWithRecoveryToken } from '../actions'; 9 | 10 | const Page: NextPage = () => { 11 | const searchParams = useSearchParams(); 12 | const { push } = useRouter(); 13 | const token = searchParams.get('code'); 14 | 15 | useEffect(() => { 16 | const handleCodeAuth = async () => { 17 | if (!token) { 18 | push('/'); 19 | return; 20 | } 21 | 22 | const { error } = await signInWithRecoveryToken(token); 23 | 24 | if (error) { 25 | toast({ title: error.message, variant: 'destructive' }); 26 | push('/'); 27 | } 28 | }; 29 | 30 | void handleCodeAuth(); 31 | }, [push, token]); 32 | 33 | return ( 34 |
35 |
36 | 37 |

38 | Reset Your Password 39 |

40 |

41 | Please enter your new password below. 42 |

43 |
44 | 45 |
46 | ); 47 | }; 48 | 49 | export default Page; 50 | -------------------------------------------------------------------------------- /apps/app/src/app/auth/welcome/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import type { NextPage } from 'next'; 4 | import { Icons, toast } from 'ui'; 5 | import { useRouter, useSearchParams } from 'next/navigation'; 6 | import { useEffect } from 'react'; 7 | import ReactConfetti from 'react-confetti'; 8 | import { signInWithRecoveryToken } from '../actions'; 9 | 10 | const Page: NextPage = () => { 11 | const searchParams = useSearchParams(); 12 | const { push } = useRouter(); 13 | const code = searchParams.get('code'); 14 | 15 | useEffect(() => { 16 | const handleCodeAuth = async () => { 17 | if (!code) { 18 | push('/'); 19 | return; 20 | } 21 | 22 | const { error } = await signInWithRecoveryToken(code); 23 | 24 | if (error) { 25 | toast({ title: error.message, variant: 'destructive' }); 26 | } 27 | 28 | setTimeout(() => { 29 | push('/'); 30 | }, 5000); 31 | }; 32 | 33 | void handleCodeAuth(); 34 | }, [code, push]); 35 | 36 | return ( 37 | <> 38 | {typeof window !== 'undefined' && window.innerHeight ? ( 39 | 40 | ) : null} 41 |
42 |
43 | 44 |

45 | Welcome to New Beginnings! 46 |

47 |

48 | Embark on a journey of discovery and innovation with us. Let's 49 | create something extraordinary together. 50 |

51 |
52 |
53 | 54 | ); 55 | }; 56 | 57 | export default Page; 58 | -------------------------------------------------------------------------------- /apps/app/src/app/experimental/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useState } from 'react'; 4 | import { Button, cn, Icons } from 'ui'; 5 | import type { NextPage } from 'next'; 6 | import { RegisterWithEmailAndPasswordAuthForm } from '../../modules/auth/components/RegisterWithEmailAndPasswordAuthForm'; 7 | import '../../modules/auth/styles/auth.css'; 8 | import { LoginAuthForm } from '../../modules/auth/components/LoginAuthForm'; 9 | 10 | const Page: NextPage = () => { 11 | const [signUpMode, setSignUpMode] = useState(false); 12 | 13 | return ( 14 |
15 |
16 |
17 |
18 |
19 |
20 | 21 |

22 | Register now! 23 |

24 |

25 | Enter your email to sign in to your account 26 |

27 |
28 | 29 |

30 | 38 |

39 |
40 |
41 |
42 |
43 |
44 | 45 |

46 | Welcome back 47 |

48 |

49 | Enter your email to sign in to your account 50 |

51 |
52 | 53 |

54 | 62 |

63 |
64 |
65 |
66 |
67 |
68 | ); 69 | }; 70 | 71 | export default Page; 72 | -------------------------------------------------------------------------------- /apps/app/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from 'next'; 2 | import { Oswald } from 'next/font/google'; 3 | import 'ui/styles/globals.css'; 4 | import React from 'react'; 5 | import { Toaster } from 'ui'; 6 | import { ThemeProvider } from '../components/layouts/ThemeProvider'; 7 | import Script from 'next/script'; 8 | 9 | const inter = Oswald({ subsets: ['latin'] }); 10 | 11 | // TODO: update the site metadata 12 | export const metadata: Metadata = { 13 | title: 'Launchpad', 14 | description: 'Turbo app starter', 15 | icons: { 16 | icon: '/favicon.ico', 17 | shortcut: '/favicon-16x16.png', 18 | apple: '/apple-touch-icon.png', 19 | }, 20 | }; 21 | 22 | // TODO: Add global providers over here 23 | const RootLayout = ({ children }: { children: React.ReactNode }) => ( 24 | 25 | 26 | 33 | {children} 34 | 35 | 36 | 37 |