├── .env.sample ├── .github ├── ISSUE_TEMPLATE │ └── feature.yml ├── pull_request_template.md ├── unused │ ├── codeql.yml │ ├── coverage-report.yml │ ├── dev-deployment.yml │ ├── production-deployment.yml │ └── staging-deployment.yml └── workflows │ ├── build-and-upload.yml │ └── build-lint-test.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .prettierignore ├── .prettierrc ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── README.md ├── ROUTING.md ├── SECURITY.md ├── STYLE_GUIDE.md ├── commitlint.config.js ├── components.json ├── eslint.config.mjs ├── next.config.ts ├── package.json ├── pnpm-lock.yaml ├── postcss.config.mjs ├── prettierrc.cjs ├── public ├── home │ └── HNG Boilerplate-Logo.png └── images │ ├── HNG Boilerplate-Logo.png │ ├── Star1.svg │ ├── WaitList │ ├── BACKGROUND.svg │ ├── Vector.svg │ ├── activity 2.svg │ ├── circle 1.svg │ ├── database.jpg │ ├── database.png │ ├── database.svg │ ├── dollar.svg │ ├── emailManagement.jpg │ ├── icon.svg │ ├── lock.svg │ ├── message.svg │ ├── payment.jpg │ ├── payment.png │ ├── phone.jpg │ ├── phone.png │ ├── pie-chart2.svg │ ├── safety.jpg │ ├── safety.png │ └── success.svg │ ├── about-us │ ├── aboutus1.svg │ ├── background.svg │ ├── ellipse.svg │ ├── our-mission.svg │ ├── our-vision.svg │ ├── team1.svg │ ├── team2.svg │ ├── team3.svg │ └── team4.svg │ ├── bell-icon.jpg │ ├── blogPage │ ├── blogCard1.png │ ├── blogCard2.png │ ├── blogCard3.png │ ├── blogCard4.png │ ├── blogCard5.png │ ├── blogCard6.png │ ├── blogHero.png │ ├── blogHero.svg │ ├── blogHero1.png │ └── utils │ │ └── index.ts │ ├── blogcommentsection │ ├── image 10.png │ └── person.svg │ ├── cancel.svg │ ├── career │ └── noJob.svg │ ├── checkmark.svg │ ├── emailConfirmation.png │ ├── facebook.svg │ ├── flags │ ├── en.svg │ ├── es.svg │ └── fr.svg │ ├── google.png │ ├── google.svg │ ├── hero-image.svg │ ├── hero-image2.svg │ ├── hero-image3.svg │ ├── hero-image4.svg │ ├── hero-image5.svg │ ├── hero-image6.svg │ ├── hero-line.svg │ ├── icon.png │ ├── integration │ ├── atlassian.svg │ ├── dropbox.svg │ ├── gdrive.svg │ ├── jira.svg │ ├── ms-office-teams.svg │ ├── ms-office.svg │ ├── notion.svg │ ├── onedrive.svg │ ├── slack.svg │ └── trello.svg │ ├── latest-articles │ ├── avatar.png │ ├── dot-icon-gray.svg │ ├── dot-icon-white.svg │ ├── post-1.png │ ├── post-2.png │ ├── post-3.png │ ├── post-4.png │ └── post-5.png │ ├── latestArticles │ ├── Climate.png │ ├── ClimateDextop.png │ ├── Future Picture.png │ ├── FutureDextop.png │ ├── Mental.png │ ├── MentalDextop.png │ ├── Networking.png │ ├── NetworkingDextop.png │ ├── Nora dextop.png │ ├── Nora mobile.png │ ├── Recipe.png │ ├── RecipeDextop.png │ ├── Styling.png │ └── StylingDextop.png │ ├── logo(large).svg │ ├── logo(small).svg │ ├── logo-text.png │ ├── newletter-email-template │ ├── Newsletter-Banner.svg │ ├── Newsletter-Discount.svg │ └── Newsletter-Star.svg │ ├── pfp.jpg │ ├── productdetails │ ├── default-image.jpg │ ├── product_image.jpg │ └── test-image.jpg │ ├── productimage.png │ ├── role-success-checkmark.png │ ├── shield.svg │ ├── squeeze.png │ ├── subscription-disabled │ ├── Payment.png │ └── payment.jpg │ ├── subscription-payment-error.svg │ ├── testimonial-image1.svg │ ├── testimonial-image2.svg │ ├── testimonial-image3.svg │ ├── tiktok.svg │ ├── user.png │ ├── welcome-email-no-image │ ├── boilerplate-logo.png │ ├── instagram-icon.png │ ├── linkedin-icon.png │ ├── reddit-icon.png │ ├── star-icon.png │ ├── tiktok-icon.png │ └── twitter-icon.png │ └── welcome-email-with-image │ ├── email-welcome.png │ └── star.png ├── src ├── actions │ ├── auth.ts │ ├── axios.ts │ ├── external │ │ └── faq.ts │ ├── fetchutil.ts │ ├── nextauth.ts │ ├── organisation.ts │ ├── subscription.ts │ └── useVersionSync.ts ├── app │ ├── (main) │ │ ├── (landing-routes) │ │ │ ├── (auth-routes) │ │ │ │ ├── layout.tsx │ │ │ │ ├── login │ │ │ │ │ └── page.tsx │ │ │ │ └── register │ │ │ │ │ └── page.tsx │ │ │ ├── (home) │ │ │ │ ├── about-us │ │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ │ ├── faqs │ │ │ │ └── page.tsx │ │ │ └── layout.tsx │ │ ├── action │ │ │ └── .gitkeep │ │ └── dashboard │ │ │ └── (main) │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ ├── api │ │ ├── auth │ │ │ └── [...nextauth] │ │ │ │ └── route.ts │ │ └── social │ │ │ └── google │ │ │ └── route.ts │ ├── csharp │ │ ├── (landing-routes) │ │ │ ├── (home) │ │ │ │ ├── about-us │ │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ │ ├── faqs │ │ │ │ └── page.tsx │ │ │ └── layout.tsx │ │ ├── action │ │ │ └── .gitkeep │ │ └── dashboard │ │ │ ├── (auth-routes) │ │ │ ├── layout.tsx │ │ │ ├── login │ │ │ │ └── page.tsx │ │ │ └── register │ │ │ │ └── page.tsx │ │ │ └── (main) │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ ├── favicon.ico │ ├── globals.css │ ├── go │ │ ├── (landing-routes) │ │ │ ├── (home) │ │ │ │ ├── about-us │ │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ │ ├── faqs │ │ │ │ └── page.tsx │ │ │ └── layout.tsx │ │ ├── action │ │ │ └── .gitkeep │ │ └── dashboard │ │ │ ├── (auth-routes) │ │ │ ├── layout.tsx │ │ │ ├── login │ │ │ │ └── page.tsx │ │ │ └── register │ │ │ │ └── page.tsx │ │ │ └── (main) │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ ├── java │ │ ├── (landing-routes) │ │ │ ├── (home) │ │ │ │ ├── about-us │ │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ │ ├── faqs │ │ │ │ └── page.tsx │ │ │ └── layout.tsx │ │ ├── action │ │ │ └── .gitkeep │ │ └── dashboard │ │ │ ├── (auth-routes) │ │ │ ├── layout.tsx │ │ │ ├── login │ │ │ │ └── page.tsx │ │ │ └── register │ │ │ │ └── page.tsx │ │ │ └── (main) │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ ├── layout.tsx │ ├── nestjs │ │ ├── (landing-routes) │ │ │ ├── (auth-routes) │ │ │ │ ├── layout.tsx │ │ │ │ ├── login │ │ │ │ │ └── page.tsx │ │ │ │ └── register │ │ │ │ │ └── page.tsx │ │ │ ├── (home) │ │ │ │ ├── about-us │ │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ │ ├── faqs │ │ │ │ └── page.tsx │ │ │ └── layout.tsx │ │ ├── action │ │ │ └── .gitkeep │ │ └── dashboard │ │ │ └── (main) │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ ├── php │ │ ├── (landing-routes) │ │ │ ├── (home) │ │ │ │ ├── about-us │ │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ │ ├── faqs │ │ │ │ └── page.tsx │ │ │ └── layout.tsx │ │ ├── action │ │ │ └── .gitkeep │ │ └── dashboard │ │ │ ├── (auth-routes) │ │ │ ├── layout.tsx │ │ │ ├── login │ │ │ │ └── page.tsx │ │ │ └── register │ │ │ │ └── page.tsx │ │ │ └── (main) │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ ├── provider.tsx │ └── python │ │ ├── (landing-routes) │ │ ├── (home) │ │ │ ├── about-us │ │ │ │ └── page.tsx │ │ │ └── page.tsx │ │ ├── faqs │ │ │ └── page.tsx │ │ └── layout.tsx │ │ ├── action │ │ └── .gitkeep │ │ └── dashboard │ │ ├── (auth-routes) │ │ ├── layout.tsx │ │ ├── login │ │ │ └── page.tsx │ │ └── register │ │ │ └── page.tsx │ │ └── (main) │ │ ├── layout.tsx │ │ └── page.tsx ├── auth.ts ├── components │ ├── about │ │ ├── CoreValues.tsx │ │ ├── ExecutiveTeam.tsx │ │ ├── Hero.tsx │ │ ├── Join.tsx │ │ ├── Mission.tsx │ │ └── OurServices.tsx │ ├── auth │ │ ├── login.tsx │ │ └── register.tsx │ ├── card │ │ ├── teamcard.tsx │ │ └── user-card.tsx │ ├── dashboard │ │ ├── main.tsx │ │ └── navbar.tsx │ ├── enviroment-switcher.tsx │ ├── faq │ │ ├── accordin.tsx │ │ └── faqpage.tsx │ ├── global │ │ ├── logo.tsx │ │ └── main-logo.tsx │ ├── homepage │ │ ├── Hero.tsx │ │ ├── HowItWorks.tsx │ │ ├── PerfectFit.tsx │ │ ├── TestimonialCard.tsx │ │ ├── Testimonials.tsx │ │ ├── UserSection.tsx │ │ ├── Video.tsx │ │ ├── svgs.tsx │ │ └── testimonials-data.ts │ ├── icons │ │ └── google-logo.tsx │ ├── miscellaneous │ │ ├── goto-top.tsx │ │ ├── heading │ │ │ └── index.tsx │ │ └── loading-spinner.tsx │ ├── navigation │ │ ├── footer │ │ │ └── index.tsx │ │ └── navbar │ │ │ ├── index.tsx │ │ │ ├── links.ts │ │ │ ├── menu.css │ │ │ └── mobile-navbar.tsx │ └── ui │ │ ├── accordion.tsx │ │ ├── avatar.tsx │ │ ├── button.tsx │ │ ├── calendar.tsx │ │ ├── card.tsx │ │ ├── checkbox.tsx │ │ ├── command.tsx │ │ ├── dialog.tsx │ │ ├── dropdown-menu.tsx │ │ ├── form.tsx │ │ ├── framer-button.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── popover.tsx │ │ ├── skeleton.tsx │ │ └── sonner.tsx ├── config │ ├── auth.config.ts │ └── env.config.ts ├── hooks │ ├── dashboard │ │ └── useOrganisation.ts │ ├── external │ │ └── use-external.ts │ └── global │ │ ├── use-enviroment.ts │ │ └── use-window-height.ts ├── middleware.ts ├── routes.ts ├── schemas │ └── index.ts ├── types │ └── index.d.ts └── utils │ └── index.ts ├── tailwind.config.ts └── tsconfig.json /.env.sample: -------------------------------------------------------------------------------- 1 | AUTH_URL= #leave for devops 2 | AUTH_SECRET=kP2Yz3v0nm1VE3mIQrImqpD6H/hP8Y+638o0uWu1K9Q 3 | AUTH_GOOGLE_ID= 4 | AUTH_GOOGLE_SECRET= 5 | PYTHON_BASE_URL= 6 | PHP_BASE_URL= 7 | NESTJS_BASE_URL= 8 | CSHARP_BASE_URL= 9 | JAVA_BASE_URL= 10 | GOLANG_BASE_URL= 11 | BASE_URL= -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.yml: -------------------------------------------------------------------------------- 1 | name: Feature 2 | description: An enhancement or feature 3 | title: "[Feature]: " 4 | labels: ["triage", "feature"] 5 | body: 6 | - type: textarea 7 | id: description 8 | attributes: 9 | label: Description 10 | description: A step-by-step description of the suggested feature/enhancement. 11 | placeholder: On the user page, you should be able to... 12 | validations: 13 | required: true 14 | - type: textarea 15 | id: acceptanceCriteria 16 | attributes: 17 | label: Acceptance Criteria 18 | description: What are the things that must be achieved for your ticket to be considered complete. 19 | validations: 20 | required: true 21 | - type: markdown 22 | attributes: 23 | value: > 24 | | Please include any screenshots which would help demonstrate the steps 25 | and point out which parts the feature is related to 26 | - type: textarea 27 | id: links 28 | attributes: 29 | label: Links 30 | description: Place links to supporting docs here. e.g. Figma 31 | value: > 32 | | [`FIGMA LINK`](LINK_HERE) 33 | - type: textarea 34 | id: images 35 | attributes: 36 | label: Images 37 | description: Paste images or image urls 38 | value: "![image](URL_HERE)" 39 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Description 4 | 5 | 6 | 7 | 8 | 9 | **Closes #issue_number_here** 10 | 11 | # Changes proposed 12 | 13 | ## What were you told to do? 14 | 15 | 16 | 17 | ## What did you do? 18 | 19 | 20 | 21 | # Check List (Check all the applicable boxes) 22 | 23 | 🚨Please review the [contribution guideline](CONTRIBUTING.md) for this repository. 24 | 25 | 26 | 27 | 35 | 36 | - [ ] My code follows the code style of this project. 37 | - [ ] This PR does not contain plagiarized content. 38 | - [ ] The title and description of the PR is clear and explains the approach. 39 | - [ ] I am making a pull request against the **dev branch** (left side). 40 | - [ ] My commit messages styles matches our requested structure. 41 | - [ ] My code additions will fail neither code linting checks nor unit test. 42 | - [ ] I am only making changes to files I was requested to. 43 | 44 | # Screenshots/Videos 45 | 46 | 47 | 49 | 50 | -------------------------------------------------------------------------------- /.github/unused/coverage-report.yml: -------------------------------------------------------------------------------- 1 | name: Coverage Report 2 | 3 | on: 4 | workflow_run: 5 | workflows: ["Build, Lint and Test"] 6 | types: 7 | - completed 8 | 9 | jobs: 10 | coverage_report: 11 | if: ${{ github.event.workflow_run.conclusion == 'success' }} 12 | runs-on: ubuntu-latest 13 | 14 | permissions: 15 | pull-requests: write 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | 20 | - name: Download coverage artifact 21 | uses: actions/download-artifact@v4 22 | with: 23 | github-token: ${{ secrets.GITHUB_TOKEN }} 24 | run-id: ${{ github.event.workflow_run.id }} 25 | name: coverage-report 26 | path: coverage 27 | 28 | - name: "Coverage Report" 29 | uses: davelosert/vitest-coverage-report-action@v2 30 | -------------------------------------------------------------------------------- /.github/unused/dev-deployment.yml: -------------------------------------------------------------------------------- 1 | name: Dev Deployment 2 | 3 | on: 4 | workflow_dispatch: 5 | # workflow_run: 6 | # workflows: ["Build and Upload"] 7 | # types: 8 | # - completed 9 | 10 | jobs: 11 | deploy_to_dev: 12 | if: ${{ github.event.workflow_run.conclusion == 'success' }} 13 | runs-on: ubuntu-latest 14 | 15 | environment: 16 | name: "dev" 17 | url: ${{ vars.URL }} 18 | 19 | steps: 20 | - name: Download build artifact 21 | uses: actions/download-artifact@v4 22 | with: 23 | github-token: ${{ secrets.GITHUB_TOKEN }} 24 | run-id: ${{ github.event.workflow_run.id }} 25 | name: boilerplate-build 26 | path: . 27 | 28 | - name: Decode and create .env file 29 | run: | 30 | echo ${{ secrets.ENV_BASE64 }} | base64 -d > .env 31 | 32 | - name: Copy Artifacts to server 33 | uses: appleboy/scp-action@v0.1.7 34 | with: 35 | host: ${{ secrets.HOST }} 36 | username: ${{ secrets.USERNAME }} 37 | password: ${{ secrets.PASSWORD }} 38 | source: ".env,boilerplate.tar.gz" 39 | target: "~/hng_boilerplate_nextjs" 40 | 41 | - name: Deploy on server 42 | uses: appleboy/ssh-action@master 43 | with: 44 | host: ${{ secrets.HOST }} 45 | username: ${{ secrets.USERNAME }} 46 | password: ${{ secrets.PASSWORD }} 47 | script: | 48 | cd ~/hng_boilerplate_nextjs 49 | tar -xzf boilerplate.tar.gz 50 | rm -f boilerplate.tar.gz 51 | cp -r .next/standalone/* . 52 | # pm2 restart nextjs_boilerplate --update-env 53 | -------------------------------------------------------------------------------- /.github/unused/production-deployment.yml: -------------------------------------------------------------------------------- 1 | name: Production Deployment 2 | 3 | on: 4 | workflow_dispatch: 5 | workflow_run: 6 | workflows: ["Build and Upload"] 7 | types: 8 | - completed 9 | branches: 10 | - main 11 | 12 | jobs: 13 | build-and-deploy: 14 | if: ${{ github.ref == 'refs/heads/main'}} && ${{ github.event.workflow_run.conclusion == 'success' }} 15 | runs-on: hng12 16 | 17 | 18 | steps: 19 | - name: Checkout Repository 20 | uses: actions/checkout@v4 21 | 22 | - name: Set up Node.js 23 | uses: actions/setup-node@v4 24 | with: 25 | node-version: '22' 26 | 27 | - name: Deploy Main 28 | run: | 29 | cd ~/boilerplate/main 30 | git reset --hard 31 | git pull 32 | cp ~/build-artifacts/boilerplate.tar.gz . 33 | tar --overwrite -xzf boilerplate.tar.gz 34 | rm -f boilerplate.tar.gz 35 | pm2 stop boilerplate_main 36 | pnpm install 37 | pm2 restart boilerplate_main --update-env -------------------------------------------------------------------------------- /.github/unused/staging-deployment.yml: -------------------------------------------------------------------------------- 1 | name: Staging Deployment 2 | 3 | on: 4 | workflow_dispatch: 5 | workflow_run: 6 | workflows: ["Build and Upload"] 7 | types: 8 | - completed 9 | branches: 10 | - staging 11 | 12 | jobs: 13 | build-and-deploy: 14 | runs-on: ubuntu-latest 15 | if: ${{ github.ref == 'refs/heads/staging'}} && ${{ github.event.workflow_run.conclusion == 'success' }} 16 | 17 | environment: 18 | name: "staging" 19 | url: ${{ vars.URL }} 20 | 21 | steps: 22 | 23 | - name: Download build artifact 24 | uses: actions/download-artifact@v4 25 | with: 26 | github-token: ${{ secrets.GITHUB_TOKEN }} 27 | run-id: ${{ github.event.workflow_run.id }} 28 | name: boilerplate-build 29 | path: . 30 | 31 | - name: Decode and create .env file 32 | run: | 33 | echo ${{ secrets.ENV_BASE64 }} | base64 -d > .env 34 | 35 | - name: Copy to server 36 | uses: appleboy/scp-action@master 37 | with: 38 | host: ${{ secrets.HOST }} 39 | username: ${{ secrets.USERNAME }} 40 | password: ${{ secrets.PASSWORD }} 41 | source: ".env,boilerplate.tar.gz" 42 | target: "~/hng_boilerplate_nextjs/staging" 43 | 44 | - name: Delete zip file 45 | run: rm -f boilerplate.tar.gz .env 46 | 47 | - name: Deploy on server 48 | uses: appleboy/ssh-action@master 49 | with: 50 | host: ${{ secrets.HOST }} 51 | username: ${{ secrets.USERNAME }} 52 | password: ${{ secrets.PASSWORD }} 53 | script: | 54 | cd ~/hng_boilerplate_nextjs/staging 55 | git add . 56 | git stash 57 | git reset --hard 58 | git pull 59 | tar -xzf boilerplate.tar.gz 60 | rm -f boilerplate.tar.gz 61 | pnpm install 62 | pm2 restart boilerplate_fe_staging --update-env 63 | -------------------------------------------------------------------------------- /.github/workflows/build-and-upload.yml: -------------------------------------------------------------------------------- 1 | name: Build and Upload 2 | 3 | on: 4 | push: 5 | branches: [staging, main] 6 | 7 | jobs: 8 | build: 9 | if: github.event.repository.fork == false 10 | runs-on: ubuntu-latest 11 | timeout-minutes: 10 12 | env: 13 | HOST: ${{ secrets.HOST }} 14 | USERNAME: ${{ secrets.USERNAME }} 15 | PASSWORD: ${{ secrets.PASSWORD }} 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | 20 | - name: Set up Node.js 21 | uses: actions/setup-node@v4 22 | with: 23 | node-version: "23" 24 | 25 | - name: Install pnpm 26 | uses: pnpm/action-setup@v4 27 | with: 28 | version: 10 29 | 30 | - name: Install dependencies 31 | run: pnpm install 32 | 33 | - name: Build Next.js application 34 | run: pnpm build 35 | 36 | - name: Archive production artifacts 37 | run: tar -czf boilerplate.tar.gz .next 38 | 39 | - name: Copy Artifacts to server 40 | run: | 41 | sshpass -p "$PASSWORD" scp -o StrictHostKeyChecking=no boilerplate.tar.gz "$USERNAME@$HOST:~/build-artifacts" 42 | 43 | - name: Delete zip file 44 | run: rm -f boilerplate.tar.gz 45 | -------------------------------------------------------------------------------- /.github/workflows/build-lint-test.yml: -------------------------------------------------------------------------------- 1 | name: Build, Lint and Test 2 | 3 | on: 4 | pull_request 5 | 6 | jobs: 7 | build_lint_test: 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - name: Checkout code 12 | uses: actions/checkout@v4 13 | 14 | - name: Set up Node.js 15 | uses: actions/setup-node@v4 16 | with: 17 | node-version: "20" 18 | 19 | - name: Install pnpm 20 | uses: pnpm/action-setup@v4 21 | with: 22 | version: 10 23 | 24 | - name: Install dependencies 25 | run: pnpm install 26 | 27 | - name: Lint code 28 | run: pnpm lint 29 | 30 | - name: Build project 31 | run: pnpm build 32 | -------------------------------------------------------------------------------- /.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 | .eslintcache 38 | .env 39 | tsconfig.tsbuildinfo 40 | .eslintcache -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | npm run commitlint ${1} -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | echo '🏗️👷 Running checks on your code before committing' 🔍🧐 4 | 5 | echo "styling your work" 🎨✨ 6 | 7 | 8 | # Check Prettier standards 9 | pnpm run check-format || 10 | ( 11 | echo '🤢🤮🤢🤮 Its so ugly!! - Your styling looks disgusting. 🤢🤮🤢🤮 12 | Prettier Check Failed. Running npm run format...'; 13 | npm run format; 14 | git add .; 15 | echo '✨ Formatting complete and changes added. Committing with the previous commit message...'; 16 | git commit --amend --no-edit; 17 | echo '✅✅ Amended commit with the new changes. Please try to push again.'; 18 | 19 | ) 20 | 21 | 22 | echo '🏗️👷 checking for eslint errors' 🔍🧐 23 | 24 | # Check ESLint Standards 25 | pnpm run lint || 26 | ( 27 | echo '😤🏀👋😤 Get that beans code out of here! 😤🏀👋😤 28 | ESLint Check Failed. Make the required changes listed above, add changes and try to commit again.' 29 | false 30 | ) 31 | 32 | echo '🏗️👷 checking for typescript errors' 🔍🧐 33 | 34 | # Check tsconfig standards 35 | pnpm run check-types || 36 | ( 37 | echo '🤡😂❌🤡 Failed Type check. 🤡😂❌🤡 38 | Are you seriously trying to write that? Make the changes required above.' 39 | false 40 | ) 41 | 42 | # npx lint-staged 43 | 44 | # If everything passes... Now we can commit 45 | echo '✅✅✅✅ You win this time... I am committing this now. ✅✅✅✅' 46 | 47 | echo '✅✅ Awesome work! ✅✅' 48 | echo '🚀⛅ Run git push to upload your changes to the remote repository ⛅🚀' -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 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 | .next/ 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 | 29 | # local env files 30 | .env*.local 31 | 32 | # vercel 33 | .vercel 34 | 35 | # typescript 36 | *.tsbuildinfo 37 | next-env.d.ts 38 | 39 | 40 | ./dist 41 | 42 | **/*.yml 43 | **/*.md 44 | **/*.json 45 | .prettierrc 46 | postcss.config.js 47 | .eslintrc.json 48 | .prettierrc 49 | next.config.js 50 | package-lock.json 51 | postcss.config.js 52 | README.md 53 | tailwind.config.ts 54 | tsconfig.json 55 | pnpm-lock.yaml -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "trailingComma": "es5", 5 | "printWidth": 80, 6 | "tabWidth": 2, 7 | "useTabs": false, 8 | "plugins": ["prettier-plugin-tailwindcss"], 9 | "tailwindAttributes": ["class", "className"], 10 | "tailwindFunctions": ["clsx", "cn"] 11 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Technical Code of Conduct 2 | 3 | ## Purpose 4 | 5 | The Technical Code of Conduct aims to create a collaborative, respectful, and productive environment for all contributors involved in technical aspects of the project, including code development, system architecture, and technical documentation. By adhering to this code, we ensure that all interactions are professional and constructive, fostering an environment where innovation and collaboration can thrive. 6 | 7 | ## Principles 8 | 9 | 1. **Respectful Collaboration** 10 | 11 | - Treat all team members with respect and professionalism. 12 | - Provide constructive feedback and accept feedback graciously. 13 | - Avoid personal attacks, insults, or derogatory comments. 14 | 15 | 2. **Inclusive Environment** 16 | 17 | - Encourage and support diversity in all forms, including but not limited to gender, race, age, sexual orientation, disability, and technical expertise. 18 | - Use inclusive language and avoid jargon that may exclude others. 19 | 20 | 3. **Quality and Integrity** 21 | 22 | - Commit to writing clean, maintainable, and efficient code. 23 | - Ensure that your contributions are tested and documented. 24 | - Avoid shortcuts that compromise code quality or security. 25 | 26 | 4. **Accountability and Responsibility** 27 | 28 | - Take responsibility for your contributions and be prepared to discuss and justify your decisions. 29 | - Own up to mistakes and work towards resolving issues promptly. 30 | - Do not plagiarize or copy code without proper attribution. 31 | 32 | 5. **Open Communication** 33 | - Communicate clearly and transparently with team members. 34 | - Share relevant information and updates regularly. 35 | - Listen actively and consider different viewpoints. 36 | 37 | ## Conduct Guidelines 38 | 39 | ### Code Contributions 40 | 41 | - Follow the project's coding standards and guidelines. 42 | - Write clear and descriptive commit messages. 43 | - Submit code reviews promptly and provide constructive feedback. 44 | - Ensure your code passes all tests before submitting a pull request. 45 | 46 | ### Reporting Issues 47 | 48 | - Report bugs, vulnerabilities, or issues as soon as they are discovered. 49 | - Provide detailed and accurate information to help diagnose and fix the issue. 50 | - Respect the confidentiality of any sensitive information. 51 | 52 | ### Collaboration Tools 53 | 54 | - Use project management and version control tools as intended. 55 | - Maintain clear and organized documentation. 56 | - Respect the guidelines for using communication platforms (e.g., Slack, email). 57 | 58 | ### Enforcement 59 | 60 | Instances of unacceptable behavior may be reported to the project maintainers or through an established reporting channel. All complaints will be reviewed and investigated promptly and fairly. Consequences of misconduct may include: 61 | 62 | - A warning 63 | - Temporary or permanent ban from the project 64 | 65 | ## Acknowledgments 66 | 67 | This Technical Code of Conduct is inspired by and adapted from various open-source community guidelines, including the [Contributor Covenant](https://www.contributor-covenant.org/) and the [Google Open Source Community Guidelines](https://opensource.google/conduct/). 68 | 69 | ## Contact 70 | 71 | For any questions or concerns regarding this Code of Conduct, please contact the Mentor on Slack. 72 | 73 | By participating in this project, you agree to abide by this Technical Code of Conduct and help create a positive and productive environment for all contributors. 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hng_boilerplate_nextjs 2 | 3 | ## Overview 4 | 5 | [Description] 6 | 7 | ## Getting Started 8 | 9 | In order to run this app locally, you should have the following programs installed on your computer: 10 | 11 | - [nodejs](https://nodejs.org/)>=20.0.0 12 | - [pnpm](https://yarnpkg.com/)>=9.4.0 13 | 14 | #### Clone this repository 15 | 16 | ``` 17 | git clone git@github.com/hngprojects/hng_boilerplate_nextjs.git 18 | cd hng_boilerplate_nextjs 19 | ``` 20 | 21 | #### Install dependencies 22 | 23 | ``` 24 | pnpm install 25 | ``` 26 | 27 | #### Start the server 28 | 29 | ``` 30 | pnpm dev 31 | ``` 32 | 33 | ## Contributing 34 | 35 | Please see [CONTRIBUTING](./CONTRIBUTING.md) 36 | -------------------------------------------------------------------------------- /ROUTING.md: -------------------------------------------------------------------------------- 1 | - / 2 | - pricing 3 | - about 4 | - help 5 | - legal 6 | - privacy-policy 7 | - terms-and-condition 8 | - career 9 | - :id (individual jobs page) 10 | - trial (squeeze page) 11 | - blog 12 | - latest (latest articles page) 13 | - :id (Individual blog page) 14 | - contact 15 | - faq 16 | - waitlist 17 | - auth 18 | - register 19 | - ?otp 20 | - organisation 21 | - login 22 | - email-link 23 | - success 24 | - forgot-password 25 | - verify-otp 26 | - success 27 | - reset-password 28 | - dashboard 29 | - products 30 | - add 31 | - :id 32 | - settings 33 | - profile 34 | - account-security 35 | - password 36 | - payment-information 37 | - checkout 38 | - cancel-subscription 39 | - notification 40 | - payment-information 41 | - data-and-privacy 42 | - language-and-region 43 | - admin 44 | - dashboard 45 | - products 46 | - add 47 | - :id 48 | - users 49 | - email-templates 50 | - squeeze 51 | - waitlist 52 | - settings 53 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | Security is very important for this project and its community. 🔒 4 | 5 | Learn more about it below. 👇 6 | 7 | ## Versions 8 | 9 | The latest version or release is supported. 10 | 11 | You are encouraged to write tests for your application and update your versions frequently after ensuring that your tests are passing. This way you will benefit from the latest features, bug fixes, and **security fixes**. 12 | 13 | ## Reporting a Vulnerability 14 | 15 | If you think you found a vulnerability, and even if you are not sure about it, please report it right away by sending an email to: security@hng.tech. Please try to be as explicit as possible, describing all the steps and example code to reproduce the security issue. 16 | 17 | The maintainers will review it thoroughly and get back to you. 18 | 19 | ## Public Discussions 20 | 21 | Please refrain from publicly discussing a potential security vulnerability. 🙊 22 | 23 | It's better to discuss privately and try to find a solution first, to limit the potential impact as much as possible. 24 | -------------------------------------------------------------------------------- /STYLE_GUIDE.md: -------------------------------------------------------------------------------- 1 | # Style Guides 2 | 3 | ## Getting Started 4 | 5 | In order to run this app locally, you should have the following programs installed on your computer: 6 | 7 | - [Node.js](https://nodejs.org/) version 20.0.0 or higher 8 | - [pnpm](https://yarnpkg.com/) version 9.4.0 or higher 9 | 10 | ##### Clone this repository 11 | 12 | ``` 13 | git clone git@github.com/hngprojects/hng_boilerplate_nextjs.git 14 | cd hng_boilerplate_nextjs 15 | ``` 16 | 17 | ##### Install dependencies 18 | 19 | ``` 20 | pnpm install 21 | ``` 22 | 23 | ##### Start the server 24 | 25 | ``` 26 | pnpm run dev 27 | ``` 28 | 29 | ## Colors 30 | 31 | ##### Navigate to 32 | 33 | ``` 34 | htpp://localhost:3000/guides 35 | ``` 36 | 37 | ## Components 38 | 39 | ##### Navigate to 40 | 41 | ``` 42 | htpp://localhost:3000/guides 43 | ``` 44 | 45 | ## Prerequisites 46 | 47 | - Follow all folder and file structure formats 48 | - Use the provided global alias for all imports, `~/*` representing `./src/*` 49 | ``` 50 | "paths": { 51 | "~/*": [ 52 | "./src/*" 53 | ] 54 | }, 55 | ``` 56 | - Use the global CSS variables 57 | - Use Tailwind CSS and shadCN exclusively. 58 | - UI components should be stored in `~/components/common` 59 | - Modal components should be stored in `~/components/modals` 60 | - Layout components should be stored in `~/components/layouts` 61 | - All tests should be stored in `~/test` 62 | - All emails are to be built with react email components and tailwind and stored in `~/emails/templates` 63 | 64 | ## Contributing 65 | 66 | Please read the [CONTRIBUTING](./CONTRIBUTING.md) file before making any contributions. 67 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parserPreset: 'conventional-changelog-conventionalcommits', 3 | extends: ['@commitlint/config-conventional'], 4 | rules: { 5 | 'body-leading-blank': [1, 'always'], 6 | 'body-max-line-length': [2, 'always', 100], 7 | 'footer-leading-blank': [1, 'always'], 8 | 'footer-max-line-length': [2, 'always', 100], 9 | 'header-max-length': [2, 'always', 100], 10 | 'subject-case': [2, 'never', ['start-case', 'pascal-case']], 11 | 'subject-empty': [2, 'never'], 12 | 'subject-full-stop': [2, 'never', '.'], 13 | 'type-case': [2, 'always', 'lower-case'], 14 | 'type-empty': [2, 'never'], 15 | 'type-enum': [ 16 | 2, 17 | 'always', 18 | [ 19 | 'build', 20 | 'chore', 21 | 'ci', 22 | 'docs', 23 | 'feat', 24 | 'fix', 25 | 'perf', 26 | 'refactor', 27 | 'revert', 28 | 'style', 29 | 'test', 30 | ], 31 | ], 32 | }, 33 | } 34 | -------------------------------------------------------------------------------- /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/app/globals.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "~/components", 15 | "utils": "~/utils", 16 | "ui": "~/components/ui", 17 | "lib": "~/lib", 18 | "hooks": "~/hooks" 19 | } 20 | } -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { dirname } from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { FlatCompat } from '@eslint/eslintrc' 4 | 5 | const __filename = fileURLToPath(import.meta.url) 6 | const __dirname = dirname(__filename) 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }) 11 | 12 | const eslintConfig = [ 13 | ...compat.extends('next/core-web-vitals', 'next/typescript'), 14 | ] 15 | 16 | export default eslintConfig 17 | -------------------------------------------------------------------------------- /next.config.ts: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {} 3 | 4 | export default nextConfig 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hng_boilerplate_nextjs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint", 10 | "prepare": "husky", 11 | "turbo": "next dev --turbo", 12 | "format": "pnpm lint --fix && pnpm prettier --write .", 13 | "check-types": "tsc --pretty --noEmit", 14 | "check-format": "prettier --check .", 15 | "commitlint": "commitlint --edit" 16 | }, 17 | "dependencies": { 18 | "@hookform/resolvers": "^4.1.2", 19 | "@ianvs/prettier-plugin-sort-imports": "^4.4.1", 20 | "@radix-ui/react-accordion": "^1.2.3", 21 | "@radix-ui/react-avatar": "^1.1.3", 22 | "@radix-ui/react-checkbox": "^1.1.4", 23 | "@radix-ui/react-dialog": "^1.1.6", 24 | "@radix-ui/react-dropdown-menu": "^2.1.6", 25 | "@radix-ui/react-icons": "^1.3.2", 26 | "@radix-ui/react-label": "^2.1.2", 27 | "@radix-ui/react-popover": "^1.1.6", 28 | "@radix-ui/react-slot": "^1.1.2", 29 | "@tanstack/react-query": "^5.66.11", 30 | "@tanstack/react-query-devtools": "^5.66.11", 31 | "axios": "^1.8.1", 32 | "class-variance-authority": "^0.7.1", 33 | "clsx": "^2.1.1", 34 | "cmdk": "1.0.4", 35 | "cors": "^2.8.5", 36 | "date-fns": "^4.1.0", 37 | "framer-motion": "^12.4.7", 38 | "lenis": "^1.1.22", 39 | "lucide-react": "^0.477.0", 40 | "next": "15.2.0", 41 | "next-auth": "5.0.0-beta.25", 42 | "next-nprogress-bar": "^2.4.7", 43 | "react": "^19.0.0", 44 | "react-day-picker": "9.5.1", 45 | "react-dom": "^19.0.0", 46 | "react-hook-form": "^7.54.2", 47 | "sonner": "^2.0.1", 48 | "swiper": "^11.2.4", 49 | "tailwind-merge": "^3.0.2", 50 | "tailwindcss-animate": "^1.0.7", 51 | "zod": "^3.24.2", 52 | "zustand": "^5.0.3" 53 | }, 54 | "devDependencies": { 55 | "@commitlint/cli": "^19.7.1", 56 | "@commitlint/config-conventional": "^19.7.1", 57 | "@eslint/eslintrc": "^3.3.0", 58 | "@types/cors": "^2.8.17", 59 | "@types/node": "^22.13.6", 60 | "@types/react": "^19.0.10", 61 | "@types/react-dom": "^19.0.4", 62 | "eslint": "^9.21.0", 63 | "eslint-config-next": "15.2.0", 64 | "husky": "^9.1.7", 65 | "lint-staged": "^15.4.3", 66 | "postcss": "^8.5.3", 67 | "prettier": "^3.5.2", 68 | "prettier-plugin-tailwindcss": "^0.6.11", 69 | "tailwindcss": "^3.4.17", 70 | "typescript": "^5.8.2" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | } 7 | 8 | export default config 9 | -------------------------------------------------------------------------------- /prettierrc.cjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | /** @typedef {import("@ianvs/prettier-plugin-sort-imports").PluginConfig & import('prettier-plugin-tailwindcss').PluginOptions} PluginConfigs */ 4 | 5 | /** @type {import('prettier').Config & PluginConfigs} */ 6 | module.exports = { 7 | tabWidth: 2, 8 | printWidth: 80, 9 | jsxSingleQuote: false, 10 | singleQuote: false, 11 | semi: true, 12 | trailingComma: 'all', 13 | arrowParens: 'always', 14 | endOfLine: 'auto', 15 | 16 | plugins: [ 17 | '@ianvs/prettier-plugin-sort-imports', 18 | 'prettier-plugin-tailwindcss', 19 | ], 20 | 21 | // #region @ianvs/prettier-plugin-sort-imports 22 | importOrder: ['', '', '^~/', '^[.][.]/', '^[.]/'], 23 | importOrderParserPlugins: ['typescript', 'jsx', 'decorators-legacy'], 24 | importOrderTypeScriptVersion: '5.0.0', 25 | // #endregion @ianvs/prettier-plugin-sort-imports 26 | } 27 | -------------------------------------------------------------------------------- /public/home/HNG Boilerplate-Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/home/HNG Boilerplate-Logo.png -------------------------------------------------------------------------------- /public/images/HNG Boilerplate-Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/HNG Boilerplate-Logo.png -------------------------------------------------------------------------------- /public/images/Star1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/WaitList/Vector.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/WaitList/activity 2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /public/images/WaitList/circle 1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /public/images/WaitList/database.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/WaitList/database.jpg -------------------------------------------------------------------------------- /public/images/WaitList/database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/WaitList/database.png -------------------------------------------------------------------------------- /public/images/WaitList/database.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/images/WaitList/dollar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/images/WaitList/emailManagement.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/WaitList/emailManagement.jpg -------------------------------------------------------------------------------- /public/images/WaitList/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /public/images/WaitList/lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/images/WaitList/message.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /public/images/WaitList/payment.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/WaitList/payment.jpg -------------------------------------------------------------------------------- /public/images/WaitList/payment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/WaitList/payment.png -------------------------------------------------------------------------------- /public/images/WaitList/phone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/WaitList/phone.jpg -------------------------------------------------------------------------------- /public/images/WaitList/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/WaitList/phone.png -------------------------------------------------------------------------------- /public/images/WaitList/pie-chart2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/images/WaitList/safety.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/WaitList/safety.jpg -------------------------------------------------------------------------------- /public/images/WaitList/safety.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/WaitList/safety.png -------------------------------------------------------------------------------- /public/images/WaitList/success.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /public/images/about-us/background.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/images/about-us/ellipse.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/bell-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/bell-icon.jpg -------------------------------------------------------------------------------- /public/images/blogPage/blogCard1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/blogPage/blogCard1.png -------------------------------------------------------------------------------- /public/images/blogPage/blogCard2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/blogPage/blogCard2.png -------------------------------------------------------------------------------- /public/images/blogPage/blogCard3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/blogPage/blogCard3.png -------------------------------------------------------------------------------- /public/images/blogPage/blogCard4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/blogPage/blogCard4.png -------------------------------------------------------------------------------- /public/images/blogPage/blogCard5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/blogPage/blogCard5.png -------------------------------------------------------------------------------- /public/images/blogPage/blogCard6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/blogPage/blogCard6.png -------------------------------------------------------------------------------- /public/images/blogPage/blogHero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/blogPage/blogHero.png -------------------------------------------------------------------------------- /public/images/blogPage/blogHero1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/blogPage/blogHero1.png -------------------------------------------------------------------------------- /public/images/blogPage/utils/index.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 2 | // @ts-nocheck 3 | export { default as blogCard1 } from '../../blogPage/blogCard1.png' 4 | export { default as blogCard3 } from '../../blogPage/blogCard3.png' 5 | export { default as blogCard2 } from '../../blogPage/blogCard2.png' 6 | export { default as blogCard4 } from '../../blogPage/blogCard4.png' 7 | export { default as blogCard5 } from '../../blogPage/blogCard5.png' 8 | export { default as blogCard6 } from '../../blogPage/blogCard1.png' 9 | export { default as blogHero } from '../../blogPage/blogHero.svg' 10 | -------------------------------------------------------------------------------- /public/images/blogcommentsection/image 10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/blogcommentsection/image 10.png -------------------------------------------------------------------------------- /public/images/blogcommentsection/person.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/images/cancel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/images/career/noJob.svg: -------------------------------------------------------------------------------- 1 | 8 | 14 | 20 | 28 | 29 | 30 | 31 | 35 | 39 | 43 | -------------------------------------------------------------------------------- /public/images/checkmark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/emailConfirmation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/emailConfirmation.png -------------------------------------------------------------------------------- /public/images/facebook.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /public/images/flags/fr.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /public/images/google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/google.png -------------------------------------------------------------------------------- /public/images/google.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/images/hero-line.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/icon.png -------------------------------------------------------------------------------- /public/images/integration/atlassian.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/images/integration/dropbox.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /public/images/integration/gdrive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /public/images/integration/jira.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/images/integration/ms-office-teams.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/images/integration/ms-office.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/images/integration/notion.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/integration/onedrive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/images/integration/slack.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /public/images/integration/trello.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /public/images/latest-articles/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latest-articles/avatar.png -------------------------------------------------------------------------------- /public/images/latest-articles/dot-icon-gray.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/latest-articles/dot-icon-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/latest-articles/post-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latest-articles/post-1.png -------------------------------------------------------------------------------- /public/images/latest-articles/post-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latest-articles/post-2.png -------------------------------------------------------------------------------- /public/images/latest-articles/post-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latest-articles/post-3.png -------------------------------------------------------------------------------- /public/images/latest-articles/post-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latest-articles/post-4.png -------------------------------------------------------------------------------- /public/images/latest-articles/post-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latest-articles/post-5.png -------------------------------------------------------------------------------- /public/images/latestArticles/Climate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/Climate.png -------------------------------------------------------------------------------- /public/images/latestArticles/ClimateDextop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/ClimateDextop.png -------------------------------------------------------------------------------- /public/images/latestArticles/Future Picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/Future Picture.png -------------------------------------------------------------------------------- /public/images/latestArticles/FutureDextop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/FutureDextop.png -------------------------------------------------------------------------------- /public/images/latestArticles/Mental.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/Mental.png -------------------------------------------------------------------------------- /public/images/latestArticles/MentalDextop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/MentalDextop.png -------------------------------------------------------------------------------- /public/images/latestArticles/Networking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/Networking.png -------------------------------------------------------------------------------- /public/images/latestArticles/NetworkingDextop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/NetworkingDextop.png -------------------------------------------------------------------------------- /public/images/latestArticles/Nora dextop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/Nora dextop.png -------------------------------------------------------------------------------- /public/images/latestArticles/Nora mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/Nora mobile.png -------------------------------------------------------------------------------- /public/images/latestArticles/Recipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/Recipe.png -------------------------------------------------------------------------------- /public/images/latestArticles/RecipeDextop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/RecipeDextop.png -------------------------------------------------------------------------------- /public/images/latestArticles/Styling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/Styling.png -------------------------------------------------------------------------------- /public/images/latestArticles/StylingDextop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/latestArticles/StylingDextop.png -------------------------------------------------------------------------------- /public/images/logo(large).svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /public/images/logo(small).svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /public/images/logo-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/logo-text.png -------------------------------------------------------------------------------- /public/images/newletter-email-template/Newsletter-Star.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/pfp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/pfp.jpg -------------------------------------------------------------------------------- /public/images/productdetails/default-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/productdetails/default-image.jpg -------------------------------------------------------------------------------- /public/images/productdetails/product_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/productdetails/product_image.jpg -------------------------------------------------------------------------------- /public/images/productdetails/test-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/productdetails/test-image.jpg -------------------------------------------------------------------------------- /public/images/productimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/productimage.png -------------------------------------------------------------------------------- /public/images/role-success-checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/role-success-checkmark.png -------------------------------------------------------------------------------- /public/images/shield.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/squeeze.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/squeeze.png -------------------------------------------------------------------------------- /public/images/subscription-disabled/Payment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/subscription-disabled/Payment.png -------------------------------------------------------------------------------- /public/images/subscription-disabled/payment.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/subscription-disabled/payment.jpg -------------------------------------------------------------------------------- /public/images/tiktok.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/images/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/user.png -------------------------------------------------------------------------------- /public/images/welcome-email-no-image/boilerplate-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/welcome-email-no-image/boilerplate-logo.png -------------------------------------------------------------------------------- /public/images/welcome-email-no-image/instagram-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/welcome-email-no-image/instagram-icon.png -------------------------------------------------------------------------------- /public/images/welcome-email-no-image/linkedin-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/welcome-email-no-image/linkedin-icon.png -------------------------------------------------------------------------------- /public/images/welcome-email-no-image/reddit-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/welcome-email-no-image/reddit-icon.png -------------------------------------------------------------------------------- /public/images/welcome-email-no-image/star-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/welcome-email-no-image/star-icon.png -------------------------------------------------------------------------------- /public/images/welcome-email-no-image/tiktok-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/welcome-email-no-image/tiktok-icon.png -------------------------------------------------------------------------------- /public/images/welcome-email-no-image/twitter-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/welcome-email-no-image/twitter-icon.png -------------------------------------------------------------------------------- /public/images/welcome-email-with-image/email-welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/welcome-email-with-image/email-welcome.png -------------------------------------------------------------------------------- /public/images/welcome-email-with-image/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/public/images/welcome-email-with-image/star.png -------------------------------------------------------------------------------- /src/actions/auth.ts: -------------------------------------------------------------------------------- 1 | 'use server' 2 | 3 | import axios from 'axios' 4 | import * as z from 'zod' 5 | import { envConfig } from '~/config/env.config' 6 | import { LoginSchema, RegisterSchema } from '~/schemas' 7 | import { AuthResponse, ErrorResponse } from '~/types' 8 | 9 | const credentialsAuth = async ( 10 | values: z.infer 11 | ): Promise => { 12 | const baseURL = envConfig.BASEURL 13 | const validatedFields = LoginSchema.safeParse(values) 14 | if (!validatedFields.success) { 15 | return { 16 | message: 'Something went wrong', 17 | status_code: 401, 18 | success: false, 19 | } 20 | } 21 | const { email, password } = validatedFields.data 22 | const payload = { email, password } 23 | try { 24 | const response = await axios.post(`${baseURL}/auth/login`, payload) 25 | return { 26 | data: response.data.user, 27 | access_token: response.data.access_token, 28 | success: true, 29 | message: 'login success', 30 | } 31 | } catch (error) { 32 | return { 33 | success: false, 34 | message: 35 | axios.isAxiosError(error) && 36 | error.response && 37 | error.response.data.message 38 | ? error.response.data.message 39 | : 'Something went wrong', 40 | status_code: 41 | axios.isAxiosError(error) && error.response 42 | ? error.response.status 43 | : undefined, 44 | } 45 | } 46 | } 47 | 48 | export const registerUser = async (values: z.infer) => { 49 | const validatedFields = RegisterSchema.safeParse(values) 50 | const baseURL = envConfig.BASEURL 51 | if (!validatedFields.success) { 52 | return { 53 | error: 'registration Failed. Please check your inputs.', 54 | } 55 | } 56 | try { 57 | const response = await axios.post( 58 | `${baseURL}/auth/register`, 59 | validatedFields.data 60 | ) 61 | 62 | return { 63 | status: response.status, 64 | data: response.data, 65 | } 66 | } catch (error) { 67 | return axios.isAxiosError(error) && error.response 68 | ? { 69 | error: error.response.data.message || 'Registration failed.', 70 | status: error.response.status, 71 | } 72 | : { 73 | error: 'An unexpected error occurred.', 74 | } 75 | } 76 | } 77 | 78 | export const resendOtp = async (email: string) => { 79 | const baseURL = process.env.BASEURL 80 | try { 81 | const response = await axios.post(`${baseURL}/auth/request/token`, { 82 | email, 83 | }) 84 | 85 | return { 86 | status: response.status, 87 | message: response.data.message, 88 | } 89 | } catch (error) { 90 | return axios.isAxiosError(error) && error.response 91 | ? { 92 | error: error.response.data.message || 'Resend OTP failed.', 93 | status: error.response.status, 94 | } 95 | : { 96 | error: 'An unexpected error occurred.', 97 | } 98 | } 99 | } 100 | 101 | export { credentialsAuth } 102 | -------------------------------------------------------------------------------- /src/actions/axios.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosInstance } from 'axios' 2 | 3 | const Calls = (): AxiosInstance => { 4 | const baseURL = process.env.BASEURL 5 | return axios.create({ 6 | baseURL, 7 | headers: { 8 | 'Content-Type': 'application/json; charset=UTF-8', 9 | 'Access-Control-Allow-Origin': '*', 10 | credentials: 'include', 11 | }, 12 | }) 13 | } 14 | 15 | const CallsWithBearer = ( 16 | baseURL: string, 17 | authorization: string 18 | ): AxiosInstance => { 19 | return axios.create({ 20 | baseURL, 21 | headers: { 22 | 'Content-Type': 'application/json; charset=UTF-8', 23 | 'Access-Control-Allow-Origin': '*', 24 | Authorization: `Bearer ${authorization}`, 25 | }, 26 | }) 27 | } 28 | 29 | export { Calls, CallsWithBearer } 30 | -------------------------------------------------------------------------------- /src/actions/external/faq.ts: -------------------------------------------------------------------------------- 1 | 'use server' 2 | 3 | import { cache } from 'react' 4 | import { isAxiosError } from 'axios' 5 | import { Calls } from '../axios' 6 | 7 | export const getFaqs = cache(async () => { 8 | const $http = Calls() 9 | 10 | try { 11 | const response = await $http.get('/faqs') 12 | 13 | return { 14 | data: response.data.data, 15 | success: true, 16 | } 17 | } catch (error) { 18 | return { 19 | success: false, 20 | message: 21 | isAxiosError(error) && error.response && error.response.data.message 22 | ? error.response.data.message 23 | : 'Something went wrong', 24 | status_code: 25 | isAxiosError(error) && error.response 26 | ? error.response.status 27 | : undefined, 28 | } 29 | } 30 | }) 31 | -------------------------------------------------------------------------------- /src/actions/fetchutil.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' 3 | 4 | interface FetchOptions 5 | extends Omit { 6 | method?: HttpMethod 7 | headers?: Record 8 | body?: TRequestBody 9 | params?: Record 10 | } 11 | 12 | interface FetchConfig { 13 | baseUrl: string 14 | defaultHeaders?: Record 15 | } 16 | 17 | export class HttpError extends Error { 18 | public statusCode: number 19 | public responseBody: any 20 | public statusText: string 21 | 22 | constructor( 23 | public response: Response, 24 | responseBody: any, 25 | statusText: string 26 | ) { 27 | super(`HTTP error! status: ${response.status}`) 28 | this.name = 'HttpError' 29 | this.statusCode = response.status 30 | this.responseBody = responseBody 31 | this.statusText = statusText 32 | } 33 | } 34 | 35 | export const createFetchUtil = (config: FetchConfig) => { 36 | const { baseUrl, defaultHeaders = {} } = config 37 | 38 | return async function fetchUtil( 39 | endpoint: string, 40 | options: FetchOptions = {} 41 | ): Promise { 42 | const { 43 | method = 'GET', 44 | headers = {}, 45 | body, 46 | params, 47 | ...restOptions 48 | } = options 49 | 50 | const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/` 51 | const normalizedEndpoint = endpoint.startsWith('/') 52 | ? endpoint.slice(1) 53 | : endpoint 54 | 55 | const url = new URL(normalizedEndpoint, normalizedBaseUrl) 56 | 57 | if (params) { 58 | Object.entries(params).forEach(([key, value]) => { 59 | url.searchParams.append(key, value) 60 | }) 61 | } 62 | 63 | const mergedHeaders = { 64 | 'Content-Type': 'application/json', 65 | ...defaultHeaders, 66 | ...headers, 67 | } 68 | 69 | const fetchOptions: RequestInit = { 70 | method, 71 | headers: mergedHeaders, 72 | ...restOptions, 73 | } 74 | 75 | if (body) { 76 | fetchOptions.body = JSON.stringify(body) 77 | } 78 | 79 | const response = await fetch(url.toString(), fetchOptions) 80 | 81 | let responseBody 82 | const contentType = response.headers.get('content-type') 83 | if (contentType && contentType.includes('application/json')) { 84 | responseBody = await response.json() 85 | } else { 86 | responseBody = await response.text() 87 | } 88 | 89 | if (!response.ok) { 90 | throw new HttpError(response, responseBody, response.statusText) 91 | } 92 | 93 | return responseBody as TResponse 94 | } 95 | } 96 | 97 | export const withAuth = (token: string): Record => ({ 98 | Authorization: `Bearer ${token}`, 99 | }) 100 | -------------------------------------------------------------------------------- /src/actions/nextauth.ts: -------------------------------------------------------------------------------- 1 | 'use server' 2 | 3 | import * as z from 'zod' 4 | import { LoginSchema } from '~/schemas' 5 | import { createFetchUtil } from './fetchutil' 6 | import { User } from '~/types' 7 | import { cookies } from 'next/headers' 8 | import { envConfig } from '~/config/env.config' 9 | 10 | export interface LoginResponse { 11 | user: User 12 | access_token: string 13 | } 14 | 15 | export const nextLogin = async (values: z.infer) => { 16 | const baseURL = process.env.BASEURL 17 | 18 | if (!baseURL) { 19 | return { 20 | status: 500, 21 | message: 'Base URL not defined', 22 | success: true, 23 | } 24 | } 25 | const api = createFetchUtil({ baseUrl: baseURL }) 26 | 27 | const response = await api<{ data: LoginResponse; access_token: string }>( 28 | '/auth/login', 29 | { 30 | method: 'POST', 31 | body: values, 32 | } 33 | ) 34 | 35 | return { 36 | data: response.data.user, 37 | access_token: response.access_token, 38 | success: true, 39 | } 40 | } 41 | 42 | export const googleAuth = async (idToken: string) => { 43 | const res = await fetch(`${envConfig.APP_URL}/api/social/google`, { 44 | method: 'POST', 45 | headers: { 46 | 'Content-Type': 'application/json', 47 | }, 48 | body: JSON.stringify({ id_token: idToken }), 49 | }) 50 | 51 | if (!res.ok) { 52 | throw new Error(`Error: ${res.status}`) 53 | } 54 | 55 | const data: { data: User; access_token: string } = await res.json() 56 | console.log(data, 'action') 57 | 58 | return { 59 | data: data.data, 60 | access_token: data.access_token, 61 | success: true, 62 | } 63 | } 64 | 65 | export const setBackend = async (backend?: string) => { 66 | const cookieStore = await cookies() 67 | if (backend) { 68 | cookieStore.set('backend', backend) 69 | } 70 | 71 | return { 72 | sucess: true, 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/actions/organisation.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hngprojects/hng_boilerplate_nextjs/d06a8e5450fb436892e07be18d4393cdee525608/src/actions/organisation.ts -------------------------------------------------------------------------------- /src/actions/subscription.ts: -------------------------------------------------------------------------------- 1 | 'use server' 2 | 3 | import { Calls } from './axios' 4 | 5 | export const makeSubscription = async (email: string) => { 6 | const baseURL = process.env.BASEURL 7 | 8 | if (!baseURL) { 9 | return { 10 | message: 'Unable to determine backend URL', 11 | success: false, 12 | } 13 | } 14 | 15 | const $http = Calls() 16 | 17 | if (!email) { 18 | return { 19 | message: 'Please provide your email', 20 | success: false, 21 | } 22 | } 23 | 24 | const payload = { email } 25 | 26 | try { 27 | const response = await $http.post('/newsletter-subscription', payload) 28 | 29 | return { 30 | data: response.data, 31 | success: true, 32 | message: 'Subscribed', 33 | } 34 | } catch (error) { 35 | return { 36 | message: 37 | error instanceof Error 38 | ? error.message 39 | : 'An error occurred during subscription', 40 | success: false, 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/actions/useVersionSync.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | 3 | const useVersionSync = (version: string) => { 4 | useEffect(() => { 5 | const currentVersion = localStorage.getItem('version') 6 | if (currentVersion === null || currentVersion !== version) { 7 | localStorage.clear() 8 | localStorage.setItem('version', version) 9 | } 10 | }, [version]) 11 | } 12 | 13 | export default useVersionSync 14 | -------------------------------------------------------------------------------- /src/app/(main)/(landing-routes)/(auth-routes)/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Suspense } from 'react' 2 | export default function AuthLayout({ 3 | children, 4 | }: Readonly<{ 5 | children: React.ReactNode 6 | }>) { 7 | return ( 8 | <> 9 | {children} 10 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /src/app/(main)/(landing-routes)/(auth-routes)/login/page.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Login from '~/components/auth/login' 3 | 4 | const page = () => { 5 | return 6 | } 7 | 8 | export default page 9 | -------------------------------------------------------------------------------- /src/app/(main)/(landing-routes)/(auth-routes)/register/page.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Register from '~/components/auth/register' 3 | 4 | const page = () => { 5 | return 6 | } 7 | 8 | export default page 9 | -------------------------------------------------------------------------------- /src/app/(main)/(landing-routes)/(home)/about-us/page.tsx: -------------------------------------------------------------------------------- 1 | import CoreValues from '~/components/about/CoreValues' 2 | import ExecutiveTeam from '~/components/about/ExecutiveTeam' 3 | import Hero from '~/components/about/Hero' 4 | import Join from '~/components/about/Join' 5 | import Mission from '~/components/about/Mission' 6 | import OurServices from '~/components/about/OurServices' 7 | 8 | const AboutUs = () => { 9 | return ( 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | ) 19 | } 20 | 21 | export default AboutUs 22 | -------------------------------------------------------------------------------- /src/app/(main)/(landing-routes)/(home)/page.tsx: -------------------------------------------------------------------------------- 1 | import Hero from '~/components/homepage/Hero' 2 | import HowItWorks from '~/components/homepage/HowItWorks' 3 | import PerfectFit from '~/components/homepage/PerfectFit' 4 | import Testimonials from '~/components/homepage/Testimonials' 5 | import UserSection from '~/components/homepage/UserSection' 6 | import Video from '~/components/homepage/Video' 7 | 8 | export default function Home() { 9 | return ( 10 | <> 11 | 12 | 13 |