diff --git a/.github/workflows/update-deps.yml b/.github/workflows/update-deps.yml deleted file mode 100644 index 5bfcdaaa..00000000 --- a/.github/workflows/update-deps.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Update dependencies - -on: - workflow_dispatch: - schedule: - - cron: '0 0 1 * *' - -jobs: - update: - strategy: - matrix: - node-version: [20.x] - - name: Update all dependencies - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - cache: npm - - run: npm ci - - - run: npx npm-check-updates -u # Update dependencies - - run: rm -Rf node_modules package-lock.json - - run: npm install - - name: Create Pull Request - uses: peter-evans/create-pull-request@v4 - with: - commit-message: 'build: update dependencies to the latest version' - title: Update dependencies to the latest version diff --git a/.vscode/settings.json b/.vscode/settings.json index 302fc307..e325df07 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -37,6 +37,7 @@ ], // Enable eslint for all supported languages + "eslint.format.enable": true, "eslint.validate": [ "javascript", "javascriptreact", diff --git a/README.md b/README.md index 03a67ad7..33ed652c 100644 --- a/README.md +++ b/README.md @@ -85,9 +85,13 @@ Clone this project and use it to create your own SaaS. You can check the live de | --- | --- | | [![Next.js Boilerplate SaaS Sign Up](public/assets/images/nextjs-boilerplate-saas-sign-up.png)](https://react-saas.com/sign-up) | [![Next.js Boilerplate SaaS Sign In](public/assets/images/nextjs-boilerplate-saas-sign-in.png)](https://react-saas.com/sign-in) | -| Landing Page Dark Mode (Pro Version) | User Dashboard Dark Mode (Pro Version) | +| Landing Page with Dark Mode (Pro Version) | User Dashboard with Dark Mode (Pro Version) | | --- | --- | -| [![Next.js Boilerplate SaaS Landing Page Dark Mode](public/assets/images/nextjs-boilerplate-saas-landing-page-dark-mode.png)](https://pro-demo.nextjs-boilerplate.com) | [![Next.js Boilerplate SaaS User Dashboard Dark Mode](public/assets/images/nextjs-boilerplate-saas-user-dashboard-dark-mode.png)](https://pro-demo.nextjs-boilerplate.com/dashboard) | +| [![Next.js Boilerplate SaaS Landing Page Dark Mode](public/assets/images/nextjs-boilerplate-saas-landing-page-dark-mode.png)](https://pro-demo.nextjs-boilerplate.com) | [![Next.js Boilerplate SaaS User Dashboard Dark Mode](public/assets/images/nextjs-boilerplate-saas-user-dashboard-sidebar-dark-mode.png)](https://pro-demo.nextjs-boilerplate.com/dashboard) | + +| User Dashboard with Sidebar (Pro Version) | +| --- | +| [![Next.js Boilerplate SaaS User Dashboard Sidebar](public/assets/images/nextjs-boilerplate-saas-user-dashboard-sidebar.png)](https://pro-demo.nextjs-boilerplate.com) | ### Features @@ -486,4 +490,6 @@ See [LICENSE](LICENSE) for more information. Made with ♥ by [CreativeDesignsGuru](https://creativedesignsguru.com) [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/cloudposse.svg?style=social&label=Follow%20%40Ixartz)](https://twitter.com/ixartz) +Looking for a custom boilerplate to kick off your project? I'd be glad to discuss how I can help you build one. Feel free to reach out anytime at contact@creativedesignsguru.com! + [![Sponsor Next JS Boilerplate](https://cdn.buymeacoffee.com/buttons/default-red.png)](https://github.com/sponsors/ixartz) diff --git a/package-lock.json b/package-lock.json index 9d29e39f..cb5b4d3e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.3", "@sentry/nextjs": "^8.34.0", @@ -8162,6 +8163,29 @@ } } }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.0.tgz", + "integrity": "sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", diff --git a/package.json b/package.json index f59caf0f..70d6b45d 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.3", "@sentry/nextjs": "^8.34.0", diff --git a/public/assets/images/nextjs-boilerplate-saas-user-dashboard-sidebar-dark-mode.png b/public/assets/images/nextjs-boilerplate-saas-user-dashboard-sidebar-dark-mode.png new file mode 100644 index 00000000..3aaba9e0 Binary files /dev/null and b/public/assets/images/nextjs-boilerplate-saas-user-dashboard-sidebar-dark-mode.png differ diff --git a/public/assets/images/nextjs-boilerplate-saas-user-dashboard-sidebar.png b/public/assets/images/nextjs-boilerplate-saas-user-dashboard-sidebar.png new file mode 100644 index 00000000..9830d1ee Binary files /dev/null and b/public/assets/images/nextjs-boilerplate-saas-user-dashboard-sidebar.png differ diff --git a/src/app/[locale]/(auth)/dashboard/page.tsx b/src/app/[locale]/(auth)/dashboard/page.tsx index b7519d22..fa902270 100644 --- a/src/app/[locale]/(auth)/dashboard/page.tsx +++ b/src/app/[locale]/(auth)/dashboard/page.tsx @@ -1,8 +1,10 @@ +import { GitHubLogoIcon } from '@radix-ui/react-icons'; import { useTranslations } from 'next-intl'; import { buttonVariants } from '@/components/ui/buttonVariants'; import { MessageState } from '@/features/dashboard/MessageState'; import { TitleBar } from '@/features/dashboard/TitleBar'; +import { SponsorLogos } from '@/features/sponsors/SponsorLogos'; const DashboardIndexPage = () => { const t = useTranslations('DashboardIndex'); @@ -36,12 +38,19 @@ const DashboardIndexPage = () => { ), })} button={( - - {t('message_state_button')} - + <> + + + {t('message_state_button')} + + +
+ +
+ )} /> diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx new file mode 100644 index 00000000..9e6f28e8 --- /dev/null +++ b/src/components/ui/separator.tsx @@ -0,0 +1,31 @@ +'use client'; + +import * as SeparatorPrimitive from '@radix-ui/react-separator'; +import * as React from 'react'; + +import { cn } from '@/utils/Helpers'; + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = 'horizontal', decorative = true, ...props }, + ref, + ) => ( + + ), +); +Separator.displayName = SeparatorPrimitive.Root.displayName; + +export { Separator }; diff --git a/src/features/dashboard/DashboardHeader.tsx b/src/features/dashboard/DashboardHeader.tsx index df6ba22b..5b157dc2 100644 --- a/src/features/dashboard/DashboardHeader.tsx +++ b/src/features/dashboard/DashboardHeader.tsx @@ -13,6 +13,7 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; +import { Separator } from '@/components/ui/separator'; import { Logo } from '@/templates/Logo'; import { getI18nPath } from '@/utils/Helpers'; @@ -71,8 +72,8 @@ export const DashboardHeader = (props: {
-
    -
  • +
      +
    • @@ -91,10 +92,14 @@ export const DashboardHeader = (props: { {/* PRO: Dark mode toggle button */} -
    • +
    • +
    • + +
    • +
    • -
        +
          {props.rightMenu}
diff --git a/src/features/landing/LogoCloud.tsx b/src/features/landing/LogoCloud.tsx index b71ec4e0..66e3f220 100644 --- a/src/features/landing/LogoCloud.tsx +++ b/src/features/landing/LogoCloud.tsx @@ -4,7 +4,7 @@ export const LogoCloud = (props: { text: string; children: React.ReactNode }) => {props.text} -
+
{props.children}
diff --git a/src/features/sponsors/SponsorLogos.tsx b/src/features/sponsors/SponsorLogos.tsx new file mode 100644 index 00000000..a3bb5d6b --- /dev/null +++ b/src/features/sponsors/SponsorLogos.tsx @@ -0,0 +1,84 @@ +/* eslint-disable react-dom/no-unsafe-target-blank */ +import Image from 'next/image'; + +import { LogoCloud } from '@/features/landing/LogoCloud'; + +export const SponsorLogos = () => ( + + + Clerk logo dark + Clerk logo light + + + + Crowdin logo dark + Crowdin logo light + + + + Sentry logo dark + Sentry logo light + + + + Nextjs SaaS Boilerplate + + +); diff --git a/src/libs/DB.ts b/src/libs/DB.ts index ffc9780e..1fe174c0 100644 --- a/src/libs/DB.ts +++ b/src/libs/DB.ts @@ -26,6 +26,7 @@ if (process.env.NEXT_PHASE !== PHASE_PRODUCTION_BUILD && Env.DATABASE_URL) { migrationsFolder: path.join(process.cwd(), 'migrations'), }); } else { + // Stores the db connection in the global scope to prevent multiple instances due to hot reloading with Next.js const global = globalThis as unknown as { client: PGlite; drizzle: PgliteDatabase }; if (!global.client) { diff --git a/src/locales/en.json b/src/locales/en.json index d6ec9978..3beb3e3f 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -102,7 +102,7 @@ "title_bar_description": "Welcome to your dashboard", "message_state_title": "Let's get started", "message_state_description": "You can customize this page by editing the file at dashboard/page.tsx", - "message_state_button": "Need Stripe Integration? Check out Next.js Boilerplate Pro" + "message_state_button": "Star on GitHub" }, "UserProfile": { "title_bar": "User Profile", diff --git a/src/locales/fr.json b/src/locales/fr.json index 868a0b63..cb2be95b 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -102,7 +102,7 @@ "title_bar_description": "Bienvenue sur votre tableau de bord", "message_state_title": "C'est parti", "message_state_description": "Vous pouvez personnaliser cette page en modifiant le fichier dans dashboard/page.tsx", - "message_state_button": "Besoin d'une intégration Stripe ? Découvrez Next.js Boilerplate Pro" + "message_state_button": "Mettez une étoile sur GitHub" }, "UserProfile": { "title_bar": "Profil utilisateur", diff --git a/src/templates/Navbar.tsx b/src/templates/Navbar.tsx index d021633e..88947314 100644 --- a/src/templates/Navbar.tsx +++ b/src/templates/Navbar.tsx @@ -18,10 +18,10 @@ export const Navbar = () => { rightMenu={( <> {/* PRO: Dark mode toggle button */} -
  • +
  • -
  • +
  • {t('sign_in')}
  • diff --git a/src/templates/Sponsors.tsx b/src/templates/Sponsors.tsx index 1818067e..10ceaad1 100644 --- a/src/templates/Sponsors.tsx +++ b/src/templates/Sponsors.tsx @@ -1,59 +1,8 @@ -/* eslint-disable react-dom/no-unsafe-target-blank */ -import Image from 'next/image'; - -import { LogoCloud } from '@/features/landing/LogoCloud'; import { Section } from '@/features/landing/Section'; +import { SponsorLogos } from '@/features/sponsors/SponsorLogos'; export const Sponsors = () => (
    - - - Clerk - - - - Crowdin - - - - Sentry - - - - Nextjs SaaS Boilerplate - - +
    );