├── .dockerignore ├── .github ├── FUNDING.yml ├── labeler.yml ├── workflows │ ├── labeler.yml │ ├── author-assign.yml │ ├── jsoncheck.yml │ ├── pr-title-checker.yml │ ├── broken-link-checker.yaml │ ├── issue-lock.yml │ ├── greetings.yml │ ├── stale-issue.yml │ ├── release-drafter.yml │ └── codeql.yml ├── PULL_REQUEST_TEMPLATE.md ├── pr-title-checker-config.json ├── release-drafter.yml └── ISSUE_TEMPLATE │ ├── project-add.yml │ ├── feature.yml │ ├── styles.yml │ ├── docs.yml │ ├── refactor_code.yml │ └── bug.yml ├── .eslintrc.json ├── app ├── favicon.ico ├── page.tsx ├── projects │ ├── page.tsx │ └── [username] │ │ └── page.tsx ├── globals.css ├── not-found.tsx ├── docs │ └── page.tsx └── layout.tsx ├── commitlint.config.js ├── .husky └── commit-msg ├── postcss.config.js ├── public ├── images │ ├── icon-192x192.png │ ├── icon-256x256.png │ ├── icon-384x384.png │ └── icon-512x512.png ├── robots.txt ├── sitemap.xml └── manifest.json ├── components ├── index.ts ├── framer-motion │ ├── index.tsx │ └── util.tsx ├── NavLink.tsx ├── ScrollToTop.tsx ├── ThemeToggle.tsx ├── MobileNavbar.tsx ├── projects │ ├── Loading.tsx │ ├── ProjectCard.tsx │ ├── ProjectList.tsx │ └── Projects.tsx ├── Navbar.tsx ├── landing │ ├── Banner.tsx │ └── Home.tsx ├── Footer.tsx └── AddYourProjectsGuide.tsx ├── pnpm-workspace.yaml ├── docker-compose.yml ├── utils ├── paginate.ts ├── techStack.ts └── searchProject.ts ├── SECURITY.md ├── next.config.js ├── .gitpod.yml ├── Dockerfile ├── .gitignore ├── tsconfig.json ├── tailwind.config.js ├── DB └── homepage-image.json ├── LICENSE ├── API └── user.tsx ├── package.json ├── README.md ├── contributing.md └── CODE_OF_CONDUCT.md /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: priyankarpal 2 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyankarpal/projectshut/HEAD/app/favicon.ico -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] }; 2 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | # projects addition: 2 | # - 'DB/*' 3 | # wait for reviewers: 4 | # - '**/*' 5 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | pnpm run commitlint ${1} 5 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /public/images/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyankarpal/projectshut/HEAD/public/images/icon-192x192.png -------------------------------------------------------------------------------- /public/images/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyankarpal/projectshut/HEAD/public/images/icon-256x256.png -------------------------------------------------------------------------------- /public/images/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyankarpal/projectshut/HEAD/public/images/icon-384x384.png -------------------------------------------------------------------------------- /public/images/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyankarpal/projectshut/HEAD/public/images/icon-512x512.png -------------------------------------------------------------------------------- /components/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Navbar } from './Navbar'; 2 | export { default as Footer } from './Footer'; 3 | export { default as ScrollToTop } from './ScrollToTop'; 4 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | # include packages in subfolders (e.g. apps/ and packages/) 3 | - 'apps/**' 4 | - 'packages/**' 5 | # if required, exclude some directories 6 | - '!**/test/**' 7 | -------------------------------------------------------------------------------- /app/page.tsx: -------------------------------------------------------------------------------- 1 | import Home from "@/components/landing/Home"; 2 | import Banner from "@/components/landing/Banner"; 3 | 4 | export default function HomePage() { 5 | return ( 6 |
7 | 8 | 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | # name: 'Labeler' 2 | # on: 3 | # - pull_request_target 4 | 5 | # jobs: 6 | # triage: 7 | # permissions: 8 | # contents: read 9 | # pull-requests: write 10 | # runs-on: ubuntu-latest 11 | # steps: 12 | # - uses: actions/labeler@v4 13 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | app: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile 8 | target: production 9 | ports: 10 | - "3000:3000" 11 | volumes: 12 | - .:/src/prod/app # Mount local code directory into the container 13 | -------------------------------------------------------------------------------- /utils/paginate.ts: -------------------------------------------------------------------------------- 1 | export const shuffleProjects = (projects: any) => { 2 | let i = projects.length; 3 | 4 | while (i--) { 5 | const j = Math.floor(Math.random() * (i + 1)); 6 | 7 | [projects[i], projects[j]] = [projects[j], projects[i]]; 8 | } 9 | 10 | return projects; 11 | }; 12 | -------------------------------------------------------------------------------- /utils/techStack.ts: -------------------------------------------------------------------------------- 1 | const techStack = [ 2 | "reactjs", 3 | "nodejs", 4 | "nextjs", 5 | "javaScript", 6 | "python", 7 | "mongodb", 8 | "typescript", 9 | "expressjs", 10 | "firebase", 11 | "tailwindcss", 12 | "angular", 13 | "redis", 14 | ]; 15 | 16 | export default techStack; 17 | -------------------------------------------------------------------------------- /app/projects/page.tsx: -------------------------------------------------------------------------------- 1 | import Projects from "@/components/projects/Projects"; 2 | import { Metadata, NextPage } from "next"; 3 | 4 | export const metadata: Metadata = { 5 | title: 'Projects', 6 | } 7 | 8 | const page: NextPage = () => { 9 | return ( 10 | 11 | ) 12 | } 13 | 14 | export default page; -------------------------------------------------------------------------------- /components/framer-motion/index.tsx: -------------------------------------------------------------------------------- 1 | import { MotionA, MotionButton, MotionDiv, MotionH1, MotionH2, MotionP, MotionSection } from "./util"; 2 | 3 | export const Motion = { 4 | div: MotionDiv, 5 | a: MotionA, 6 | p: MotionP, 7 | h1: MotionH1, 8 | h2: MotionH2, 9 | button: MotionButton, 10 | section: MotionSection, 11 | }; 12 | -------------------------------------------------------------------------------- /.github/workflows/author-assign.yml: -------------------------------------------------------------------------------- 1 | # name: 'Author Assign' 2 | 3 | # on: 4 | # pull_request_target: 5 | # types: [opened, reopened] 6 | 7 | # jobs: 8 | # assign-author: 9 | # runs-on: ubuntu-latest 10 | # steps: 11 | # - uses: toshimaru/auto-author-assign@v1.1.0 12 | # with: 13 | # repo-token: '${{ secrets.GITHUB_TOKEN }}' 14 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Related Issue 2 | 3 | 4 | 5 | ## Description 6 | 7 | 8 | 9 | ## Screenshots 10 | 11 | 12 | -------------------------------------------------------------------------------- /.github/workflows/jsoncheck.yml: -------------------------------------------------------------------------------- 1 | # name: JSON check 2 | 3 | # on: 4 | # push: 5 | # paths: 6 | # - '**.json' 7 | # pull_request: 8 | 9 | # jobs: 10 | # test: 11 | # runs-on: ubuntu-latest 12 | # steps: 13 | # - uses: actions/checkout@v3 14 | # - name: json-syntax-check 15 | # uses: limitusus/json-syntax-check@v2 16 | # with: 17 | # pattern: "\\.json$" 18 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Current projects' supported versions. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 1.5.x | :white_check_mark: | 10 | | < 1.0 | :x: | 11 | 12 | ## Reporting a Vulnerability 13 | 14 | If you found a BUG or Vulnerability you can contact me on [Twitter](https://twitter.com/priyankarpal/) 15 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: Googlebot 2 | Disallow: 3 | User-agent: googlebot-image 4 | Disallow: 5 | User-agent: googlebot-mobile 6 | Disallow: 7 | User-agent: MSNBot 8 | Disallow: 9 | User-agent: Slurp 10 | Disallow: 11 | User-agent: yahoo-mmcrawler 12 | Disallow: 13 | User-agent: yahoo-blogs/v3.9 14 | Disallow: 15 | User-agent: * 16 | Disallow: 17 | Crawl-delay: 20 18 | Sitemap: https://projectshut.vercel.app/sitemap.xml 19 | 20 | -------------------------------------------------------------------------------- /utils/searchProject.ts: -------------------------------------------------------------------------------- 1 | export const searchProject = (projects: any, title: string, type: string) => { 2 | return title.length > 0 3 | ? projects.filter((project: any) => 4 | type === "project" 5 | ? project.title.toLowerCase().includes(title.toLowerCase()) 6 | : type === "author" 7 | ? project.username.toLowerCase().includes(title.toLowerCase()) 8 | : false 9 | ) 10 | : []; 11 | }; 12 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const withPWA = require("next-pwa")({ 3 | dest: "public", 4 | register: true, 5 | skipWaiting: true, 6 | }); 7 | 8 | const nextConfig = { 9 | images: { 10 | domains: [ 11 | "user-images.githubusercontent.com", 12 | "raw.githubusercontent.com", 13 | "images.weserv.nl", 14 | "github.com", 15 | ], 16 | }, 17 | trailingSlash: true 18 | }; 19 | 20 | module.exports = withPWA(nextConfig); 21 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | # This configuration file was automatically generated by Gitpod. 2 | # Please adjust to your needs (see https://www.gitpod.io/docs/introduction/learn-gitpod/gitpod-yaml) 3 | # and commit this file to your remote git repository to share the goodness with others. 4 | 5 | # Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart 6 | 7 | tasks: 8 | - init: pnpm install && pnpm run build 9 | command: pnpm run start 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/projects/[username]/page.tsx: -------------------------------------------------------------------------------- 1 | import ProjectList from "@/components/projects/ProjectList"; 2 | import { Metadata, ResolvingMetadata } from 'next' 3 | 4 | type Props = { 5 | params: { username: string } 6 | } 7 | 8 | export async function generateMetadata({ params }: Props): Promise { 9 | const title = params.username[0].toUpperCase() + params.username.slice(1) 10 | return { 11 | title: title, 12 | } 13 | } 14 | 15 | export default function page() { 16 | return ( 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/pr-title-checker.yml: -------------------------------------------------------------------------------- 1 | # name: 'PR Title Checker' 2 | # on: 3 | # pull_request_target: 4 | # types: 5 | # - opened 6 | # - edited 7 | # - synchronize 8 | # - labeled 9 | # - unlabeled 10 | 11 | # jobs: 12 | # check: 13 | # runs-on: ubuntu-latest 14 | # steps: 15 | # - uses: thehanimo/pr-title-checker@v1.3.7 16 | # with: 17 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | # pass_on_octokit_error: false 19 | # configuration_path: '.github/pr-title-checker-config.json' 20 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Stage 1: Build 2 | FROM node:latest AS build 3 | 4 | WORKDIR /src/dev/app 5 | 6 | COPY package.json /src/dev/app 7 | 8 | # Install dependencies 9 | RUN npm install -g pnpm && pnpm install 10 | 11 | # Copy the rest of the application code 12 | COPY . /src/dev/app 13 | 14 | # Stage 2: Production 15 | FROM node:alpine AS production 16 | 17 | WORKDIR /src/prod/app 18 | 19 | # Copy only necessary files from the build stage 20 | COPY --from=build /src/dev/app /src/prod/app 21 | 22 | # Install pnpm in the production stage 23 | RUN npm install -g pnpm 24 | 25 | # Expose port 26 | EXPOSE 3000 27 | 28 | # Command to run the application in production 29 | CMD ["pnpm", "run", "dev"] 30 | -------------------------------------------------------------------------------- /.github/workflows/broken-link-checker.yaml: -------------------------------------------------------------------------------- 1 | # name: Broken Link Checker 2 | # on: 3 | # repository_dispatch: 4 | # types: [test] 5 | # workflow_dispatch: 6 | # schedule: 7 | # - cron: "00 18 * * *" 8 | # jobs: 9 | # linkChecker: 10 | # runs-on: ubuntu-latest 11 | # steps: 12 | # - name: Checkout 13 | # uses: actions/checkout@v4 14 | # - name: Check Links 15 | # uses: lycheeverse/lychee-action@v1.10.0 16 | # with: 17 | # args: --verbose --no-progress './**/*.md' './**/*.html' './**/*.rst' --exclude-mail --exclude 'http://localhost:*/*' 18 | # env: 19 | # GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 20 | -------------------------------------------------------------------------------- /.github/pr-title-checker-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "LABEL": { 3 | "name": "title-needs-formatting", 4 | "color": "EEEEEE" 5 | }, 6 | "CHECKS": { 7 | "prefixes": [ 8 | "fix: ", 9 | "feat: ", 10 | "docs: ", 11 | "test: ", 12 | "chore: ", 13 | "ci: ", 14 | "perf: ", 15 | "refactor: ", 16 | "revert: ", 17 | "style: ", 18 | "data:", 19 | "fix(", 20 | "feat(", 21 | "docs(", 22 | "chore(", 23 | "ci(", 24 | "perf(", 25 | "refactor(", 26 | "revert(", 27 | "style(", 28 | "test(" 29 | ] 30 | }, 31 | "MESSAGES": { 32 | "success": "All OK", 33 | "failure": "Failing CI test", 34 | "notice": "" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # .vscode 9 | /.vscode 10 | 11 | # testing 12 | /coverage 13 | 14 | # next.js 15 | /.next/ 16 | /out/ 17 | 18 | # production 19 | /build 20 | 21 | # misc 22 | .DS_Store 23 | *.pem 24 | 25 | # debug 26 | npm-debug.log* 27 | yarn-debug.log* 28 | yarn-error.log* 29 | 30 | # local env files 31 | .env*.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | # typescript 37 | *.tsbuildinfo 38 | next-env.d.ts 39 | 40 | # ignore package-lock 41 | package-lock.json 42 | 43 | yarn.lock 44 | 45 | sw.js 46 | sw.js.map 47 | workbox-3576cac3.js 48 | workbox-3576cac3.js.map 49 | 50 | workbox-80ca14c3.js -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "plugins": [ 18 | { 19 | "name": "next" 20 | } 21 | ], 22 | "paths": { 23 | "@/*": ["./*"] 24 | } 25 | }, 26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 27 | "exclude": ["node_modules"] 28 | } -------------------------------------------------------------------------------- /.github/workflows/issue-lock.yml: -------------------------------------------------------------------------------- 1 | # name: 'Lock new issues' 2 | 3 | # on: 4 | # issues: 5 | # types: opened 6 | 7 | # permissions: 8 | # issues: write 9 | 10 | # jobs: 11 | # action: 12 | # runs-on: ubuntu-latest 13 | # steps: 14 | # - uses: dessant/repo-lockdown@v3 15 | # with: 16 | # close-issue: false 17 | # exclude-issue-labels: '🏁 status: ready for dev' 18 | # process-only: 'issues' 19 | # skip-closed-issue-comment: true 20 | # issue-comment: > 21 | # To reduce notifications, issues are locked. Your issue will be unlock when we will add label as `🏁 status: ready for dev`. Check out the [contributing guide](https://github.com/priyankarpal/ProjectsHut/blob/main/contributing.md) for more information. 22 | -------------------------------------------------------------------------------- /components/NavLink.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import Link from "next/link"; 3 | import { usePathname } from "next/navigation"; 4 | import { LinkProps } from "next/link"; 5 | import { ReactNode } from "react"; 6 | import { ComponentProps } from "react"; 7 | 8 | type Props = LinkProps & Omit,"className"> & { 9 | className: string | ((active:boolean) => string); 10 | children: ReactNode; 11 | } 12 | 13 | export const NavLink: React.FC = ({children,href,className,...rest}) => { 14 | const activePath = usePathname(); 15 | 16 | const actualClass = typeof className === 'function' ? className(activePath === href || activePath === href + "/") : className; 17 | 18 | return ( 19 | 20 | {children} 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./pages/**/*.{js,ts,jsx,tsx,mdx}", 5 | "./components/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./app/**/*.{js,ts,jsx,tsx,mdx}", 7 | ], 8 | 9 | darkMode: 'class', // create dark mode class 10 | 11 | theme: { 12 | screens: { 13 | xsm: "240px", 14 | xs: "400px", 15 | sm: "640px", 16 | md: "760px", 17 | tab: "840px", 18 | lg: "1024px", 19 | xl: "1280px", 20 | }, 21 | 22 | extend: { 23 | fontFamily: { 24 | inter: ["Inter", "sans-serif"], 25 | }, 26 | colors: { 27 | // these are the theme colors don't change them 28 | primary: "#A66EFC", 29 | secondary: "#000513", 30 | }, 31 | }, 32 | }, 33 | }; 34 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | # name-template: 'v$RESOLVED_VERSION 🌈' 2 | # tag-template: 'v$RESOLVED_VERSION' 3 | # categories: 4 | # - title: '🚀 Features' 5 | # labels: 6 | # - '✨ goal: improvement' 7 | # - '⭐ goal: addition' 8 | # - title: '🐛 Bug Fixes' 9 | # labels: 10 | # - '🛠 goal: fix' 11 | # - title: '🧰 Maintenance' 12 | # labels: 13 | # - 'chore' 14 | # - '🛠 goal: refactor' 15 | # change-template: '- $TITLE @$AUTHOR (#$NUMBER)' 16 | # change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. 17 | # version-resolver: 18 | # major: 19 | # labels: 20 | # - 'major' 21 | # minor: 22 | # labels: 23 | # - 'minor' 24 | # patch: 25 | # labels: 26 | # - 'patch' 27 | # default: patch 28 | # template: | 29 | # ## Changes 30 | 31 | # $CHANGES 32 | -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | 3 | ::-webkit-scrollbar { 4 | width: 10px; 5 | } 6 | 7 | ::-webkit-scrollbar-thumb { 8 | @apply bg-gray-300 dark:bg-gray-600; 9 | border-radius: 10px; 10 | } 11 | 12 | html { 13 | font-family: "Inter", sans-serif; 14 | } 15 | 16 | body { 17 | @apply bg-white dark:bg-secondary text-gray-900 dark:text-gray-100 transition-colors duration-300; 18 | } 19 | 20 | /* animated image */ 21 | @keyframes floating { 22 | 0% { 23 | transform: translate(0, 0); 24 | } 25 | 26 | 50% { 27 | transform: translate(0, 8px); 28 | } 29 | 30 | 100% { 31 | transform: translate(0, 0); 32 | } 33 | } 34 | 35 | .floating-image { 36 | animation-name: floating; 37 | animation-duration: 3s; 38 | animation-timing-function: ease-in-out; 39 | animation-iteration-count: infinite; 40 | } 41 | 42 | @tailwind components; 43 | @tailwind utilities; 44 | -------------------------------------------------------------------------------- /public/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | https://projectshut.vercel.app/ 10 | 2023-05-26T14:19:26+00:00 11 | 12 | 13 | 14 | https://projectshut.vercel.app/projects 15 | 2023-05-26T14:19:26+00:00 16 | 17 | 18 | 19 | https://projectshut.vercel.app/docs 20 | 2023-05-26T14:19:26+00:00 21 | 22 | 23 | 24 | https://github.com/priyankarpal/ProjectsHut 25 | 2023-05-26T14:19:26+00:00 26 | 27 | 28 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "theme_color": "#A66EFC", 3 | "background_color": "#000513", 4 | "display": "standalone", 5 | "scope": "/", 6 | "start_url": "/", 7 | "name": "Projectshut", 8 | "short_name": "Projectshut", 9 | "description": "Projectshut is an open source web app that enables users to freely publish their projects and create user profiles within the platform", 10 | "icons": [ 11 | { 12 | "src": "/images/icon-192x192.png", 13 | "sizes": "192x192", 14 | "type": "image/png" 15 | }, 16 | { 17 | "src": "/images/icon-256x256.png", 18 | "sizes": "256x256", 19 | "type": "image/png" 20 | }, 21 | { 22 | "src": "/images/icon-384x384.png", 23 | "sizes": "384x384", 24 | "type": "image/png" 25 | }, 26 | { 27 | "src": "/images/icon-512x512.png", 28 | "sizes": "512x512", 29 | "type": "image/png" 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /DB/homepage-image.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "url": "https://raw.githubusercontent.com/Swpn0neel/ImageStorage/main/ProjectsHut%20img/1.png", 4 | "alt": "a person working on a laptop" 5 | }, 6 | { 7 | "url": "https://raw.githubusercontent.com/Swpn0neel/ImageStorage/main/ProjectsHut%20img/2.png", 8 | "alt": "laptop" 9 | }, 10 | { 11 | "url": "https://raw.githubusercontent.com/Swpn0neel/ImageStorage/main/ProjectsHut%20img/3.png", 12 | "alt": "Computer setup" 13 | }, 14 | { 15 | "url": "https://raw.githubusercontent.com/Swpn0neel/ImageStorage/main/ProjectsHut%20img/4.png", 16 | "alt": "laptop" 17 | }, 18 | { 19 | "url": "https://raw.githubusercontent.com/Swpn0neel/ImageStorage/main/ProjectsHut%20img/5.png", 20 | "alt": "lappy" 21 | }, 22 | { 23 | "url": "https://raw.githubusercontent.com/Swpn0neel/ImageStorage/main/ProjectsHut%20img/6.png", 24 | "alt": "hacking" 25 | }, 26 | { 27 | "url": "https://raw.githubusercontent.com/Swpn0neel/ImageStorage/main/ProjectsHut%20img/7.png", 28 | "alt": "Developer" 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /app/not-found.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link'; 2 | 3 | export default function NotFound() { 4 | return ( 5 |
6 |
7 |
8 |
9 |
10 |

11 | Oh no! It seems like you've taken a wrong turn. 12 |

13 |

14 | Don't worry, though! Navigate to homepage. 15 |

16 |
17 |
18 |
19 |
20 |
21 | ); 22 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/project-add.yml: -------------------------------------------------------------------------------- 1 | name: 🌱 Project Addition 2 | description: Add a new project to the list 3 | title: "chore: project addition by " 4 | labels: 5 | [ 6 | "projects addition", 7 | "🚦status: awaiting triage", 8 | "good first issue", 9 | "🟩 priority: low", 10 | ] 11 | body: 12 | - type: textarea 13 | id: project-add 14 | attributes: 15 | label: Add a new project to the list 16 | validations: 17 | required: true 18 | - type: checkboxes 19 | id: terms 20 | attributes: 21 | label: "Record" 22 | options: 23 | - label: I have checked the existing [issues](https://github.com/priyankarpal/ProjectsHut/issues) 24 | required: true 25 | 26 | - label: I have read the [Contributing Guidelines](https://github.com/priyankarpal/ProjectsHut/blob/main/contributing.md) 27 | required: true 28 | 29 | - label: I agree to follow this project's [Code of Conduct](https://github.com/priyankarpal/ProjectsHut/blob/main/CODE_OF_CONDUCT.md) 30 | required: true 31 | 32 | - label: I want to work on this issue 33 | -------------------------------------------------------------------------------- /.github/workflows/greetings.yml: -------------------------------------------------------------------------------- 1 | # name: 'Greetings' 2 | 3 | # on: 4 | # fork: 5 | # push: 6 | # branches: [main] 7 | # issues: 8 | # types: [opened] 9 | # pull_request_target: 10 | # types: [opened] 11 | 12 | # jobs: 13 | # welcome: 14 | # runs-on: ubuntu-latest 15 | # steps: 16 | # - uses: actions/checkout@v1 17 | # - uses: EddieHubCommunity/gh-action-community/src/welcome@main 18 | # with: 19 | # github-token: ${{ secrets.GITHUB_TOKEN }} 20 | # issue-message: 'Congratulations, @${{ github.actor }}! 🎉 Thank you for creating your issue. Your contribution is greatly appreciated and we look forward to working with you to resolve the issue. Keep up the great work!' 21 | # pr-message: 'Great job, @${{ github.actor }}! 🎉 Thank you for submitting your first pull request. Your contribution is valuable and we appreciate your efforts to improve our project.' 22 | # footer: 'We will promptly review your changes and offer feedback. Keep up the excellent work! Kindly remember to check our [contributing guidelines](https://github.com/priyankarpal/ProjectsHut/blob/main/contributing.md)' 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Priyankar Pal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.yml: -------------------------------------------------------------------------------- 1 | name: ✨ Feature Request 2 | description: Suggest a feature request 3 | title: "feat:" 4 | labels: ["⭐ goal: addition", "🚦status: awaiting triage"] 5 | body: 6 | - type: textarea 7 | id: what-feature 8 | attributes: 9 | label: What feature? 10 | placeholder: Add descriptions 11 | validations: 12 | required: true 13 | - type: textarea 14 | id: screenshots 15 | attributes: 16 | label: Add screenshots 17 | placeholder: Add screenshots 18 | validations: 19 | required: true 20 | - type: checkboxes 21 | id: terms 22 | attributes: 23 | label: "Record" 24 | options: 25 | - label: I have checked the existing [issues](https://github.com/priyankarpal/ProjectsHut/issues) 26 | required: true 27 | 28 | - label: I have read the [Contributing Guidelines](https://github.com/priyankarpal/ProjectsHut/blob/main/contributing.md) 29 | required: true 30 | 31 | - label: I agree to follow this project's [Code of Conduct](https://github.com/priyankarpal/ProjectsHut/blob/main/CODE_OF_CONDUCT.md) 32 | required: true 33 | 34 | 35 | 36 | - label: I want to work on this issue 37 | -------------------------------------------------------------------------------- /components/ScrollToTop.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | import React, { useEffect, useState } from 'react'; 3 | import { FaArrowUp } from 'react-icons/fa'; 4 | 5 | function BackToTopButton() { 6 | const [btnVisiblity, setBtnVisiblity] = useState(false); 7 | 8 | const handleScroll = () => { 9 | window.scrollTo({ top: 0, behavior: 'smooth' }); 10 | }; 11 | useEffect(() => { 12 | const toggleVisiblity = () => { 13 | window.scrollY > 250 ? setBtnVisiblity(true) : setBtnVisiblity(false); 14 | }; 15 | window.addEventListener('scroll', toggleVisiblity); 16 | return () => { 17 | window.removeEventListener('scroll', toggleVisiblity); 18 | }; 19 | }, []); 20 | 21 | return ( 22 | 32 | ); 33 | }; 34 | 35 | export default BackToTopButton; 36 | -------------------------------------------------------------------------------- /components/ThemeToggle.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | // This component serves as the light/dark mode toggle switch. 4 | 5 | import { useState, useEffect } from 'react' 6 | import { FiSun, FiMoon } from 'react-icons/fi' 7 | 8 | export const ThemeToggle = () => { 9 | const [darkMode, setDarkMode] = useState(true) 10 | 11 | useEffect(() => { 12 | const theme = localStorage.getItem('theme') 13 | if (theme === 'light') setDarkMode(false) 14 | else document.documentElement.classList.add('dark') 15 | }, []) 16 | 17 | const toggleTheme = () => { 18 | if (darkMode) { 19 | document.documentElement.classList.remove('dark') 20 | localStorage.setItem('theme', 'light') 21 | } else { 22 | document.documentElement.classList.add('dark') 23 | localStorage.setItem('theme', 'dark') 24 | } 25 | setDarkMode(!darkMode) 26 | } 27 | 28 | return ( 29 | 40 | ) 41 | } -------------------------------------------------------------------------------- /API/user.tsx: -------------------------------------------------------------------------------- 1 | import { FaGithub } from "react-icons/fa"; 2 | 3 | interface userType { 4 | bio?: string; 5 | social_accounts: socialMediaType[]; 6 | } 7 | 8 | interface socialMediaType { 9 | provider?: string; 10 | url?: string; 11 | icon?: JSX.Element; 12 | } 13 | 14 | export const getUserData = async ( 15 | username: string 16 | ): Promise => { 17 | try { 18 | const [res, socRes] = await Promise.all([ 19 | fetch(`https://api.github.com/users/${username}`).then((res) => 20 | res.json() 21 | ), 22 | fetch(`https://api.github.com/users/${username}/social_accounts`).then( 23 | (res) => res.json() 24 | ), 25 | ]); 26 | 27 | const filteredSoc = socRes.filter( 28 | (obj: socialMediaType) => 29 | obj.provider === "linkedin" || obj.provider === "twitter" 30 | ); 31 | 32 | const githubUrl = { 33 | provider: "github", 34 | url: `https://github.com/${username}`, 35 | icon: , 36 | }; 37 | 38 | const social_accounts = [githubUrl, ...filteredSoc]; 39 | const userData: userType = { 40 | social_accounts: social_accounts, 41 | }; 42 | 43 | return { ...res, ...userData }; 44 | } catch (error) { 45 | console.error("Error fetching data:", error); 46 | return undefined; 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /app/docs/page.tsx: -------------------------------------------------------------------------------- 1 | import AddYourProjectsGuide from "@/components/AddYourProjectsGuide"; 2 | import { Metadata } from "next"; 3 | 4 | export const metadata: Metadata = { 5 | title: 'Docs', 6 | } 7 | 8 | export default function page() { 9 | return ( 10 |
11 |
12 | 35 |
36 | 37 |
38 | ) 39 | } 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-migrate", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "prepare": "pnpx husky install", 10 | "commitlint": "commitlint --edit", 11 | "preinstall": "npx only-allow pnpm" 12 | }, 13 | "dependencies": { 14 | "@emotion/react": "^11.13.3", 15 | "@emotion/styled": "^11.13.0", 16 | "@headlessui/react": "^2.1.8", 17 | "@types/node": "22.10.5", 18 | "@types/react": "18.3.10", 19 | "@types/react-dom": "18.3.0", 20 | "autoprefixer": "10.4.20", 21 | "eslint": "9.11.1", 22 | "eslint-config-next": "14.2.14", 23 | "framer-motion": "^11.15.0", 24 | "next": "^14.2.14", 25 | "next-pwa": "^5.6.0", 26 | "pnpm": "^9.15.3", 27 | "postcss": "8.4.47", 28 | "react": "18.3.1", 29 | "react-dom": "18.3.1", 30 | "react-icons": "^5.3.0", 31 | "react-infinite-scroll-component": "^6.1.0", 32 | "react-router-dom": "^6.26.2", 33 | "react-syntax-highlighter": "^15.5.0", 34 | "sharp": "^0.33.5", 35 | "tailwindcss": "3.4.13", 36 | "typescript": "5.7.3" 37 | }, 38 | "devDependencies": { 39 | "@commitlint/cli": "^19.5.0", 40 | "@commitlint/config-conventional": "^19.5.0", 41 | "@types/react-syntax-highlighter": "^15.5.13", 42 | "husky": "^9.1.6" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/styles.yml: -------------------------------------------------------------------------------- 1 | name: 👯‍♂️ Style Changing Request 2 | description: Suggest a style design 3 | title: '[style]: ' 4 | labels: ["✨ goal: improvement","🚦status: awaiting triage","🕹 aspect: interface"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this template! 10 | - type: textarea 11 | id: style-idea 12 | attributes: 13 | label: What's the style idea? 14 | placeholder: Add descriptions 15 | 16 | validations: 17 | required: true 18 | - type: textarea 19 | id: screenshots 20 | attributes: 21 | label: Add screenshots 22 | 23 | placeholder: Add screenshots 24 | 25 | - type: checkboxes 26 | id: terms 27 | attributes: 28 | label: "Record" 29 | 30 | options: 31 | - label: I have checked the existing [issues](https://github.com/priyankarpal/ProjectsHut/issues) 32 | required: true 33 | 34 | - label: I have read the [Contributing Guidelines](https://github.com/priyankarpal/ProjectsHut/blob/main/contributing.md) 35 | required: true 36 | 37 | - label: I agree to follow this project's [Code of Conduct](https://github.com/priyankarpal/ProjectsHut/blob/main/CODE_OF_CONDUCT.md) 38 | required: true 39 | 40 | 41 | 42 | - label: I want to work on this issue 43 | 44 | -------------------------------------------------------------------------------- /components/framer-motion/util.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | import * as React from "react"; 3 | import { motion, HTMLMotionProps } from "framer-motion"; 4 | 5 | type MotionTags = "div" | "a" | "p" | "h1" | "h2" | "button" | "section"; 6 | 7 | type MotionComponent = React.ForwardRefRenderFunction< 8 | Element, 9 | HTMLMotionProps 10 | >; 11 | 12 | export const createMotionComponent = ( 13 | tag: T 14 | ): MotionComponent => { 15 | const MotionTag = motion[tag] as any; 16 | 17 | const MotionComponent: MotionComponent = ( 18 | { className, children, ...props }, 19 | ref 20 | ) => { 21 | return ( 22 | 23 | {children} 24 | 25 | ); 26 | }; 27 | 28 | MotionComponent.displayName = `Motion.${tag}`; 29 | 30 | return MotionComponent; 31 | }; 32 | 33 | export const MotionDiv = React.forwardRef(createMotionComponent("div")); 34 | export const MotionA = React.forwardRef(createMotionComponent("a")); 35 | export const MotionP = React.forwardRef(createMotionComponent("p")); 36 | export const MotionH1 = React.forwardRef(createMotionComponent("h1")); 37 | export const MotionH2 = React.forwardRef(createMotionComponent("h2")); 38 | export const MotionButton = React.forwardRef(createMotionComponent("button")); 39 | export const MotionSection = React.forwardRef(createMotionComponent("section")); 40 | -------------------------------------------------------------------------------- /.github/workflows/stale-issue.yml: -------------------------------------------------------------------------------- 1 | # name: 'Close Stale Issues & PRs' 2 | # on: 3 | # schedule: 4 | # - cron: '0 8 * * *' 5 | 6 | # jobs: 7 | # stale: 8 | # runs-on: ubuntu-22.04 9 | # steps: 10 | # - uses: actions/stale@v4.1.1 11 | # with: 12 | # # stale issue labels 13 | # stale-issue-label: 'no-issue-activity' 14 | # exempt-issue-labels: 'work-in-progress' 15 | # # stale pr lables 16 | # stale-pr-label: 'no-pr-activity' 17 | # exempt-pr-labels: 'work-in-progress' 18 | # # issue close & warning days 19 | # days-before-issue-stale: 15 20 | # days-before-issue-close: 2 21 | # # pr close & warning days 22 | # days-before-pr-stale: 15 23 | # days-before-pr-close: 2 24 | # # stale issue messages 25 | # stale-issue-message: > 26 | # This issue has been open for a few days with no activity. It will be closed soon if no further activity occurs. 27 | # close-issue-message: > 28 | # This issue has been closed because it has not received any activity in the last few days 29 | # # pr issue messages 30 | # stale-pr-message: 'This PR has been open few days with no activity. It will be closed soon if no further activity occurs' 31 | # close-pr-message: 'This PR has been closed because it has not received any activity in the last few days' 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/docs.yml: -------------------------------------------------------------------------------- 1 | name: 🔖 Documentation update 2 | description: Improve Documentation 3 | title: "docs:" 4 | labels: 5 | [ 6 | "📄 aspect: text", 7 | "🚦status: awaiting triage", 8 | "✨ goal: improvement", 9 | "good first issue", 10 | "🟨 priority: medium", 11 | ] 12 | body: 13 | - type: textarea 14 | id: improve-docs 15 | attributes: 16 | label: what's wrong with the documentation? 17 | description: which things do we need to add? 18 | placeholder: Add description 19 | validations: 20 | required: true 21 | - type: textarea 22 | id: screenshots 23 | attributes: 24 | label: Add screenshots 25 | description: Add screenshots to see the demo 26 | placeholder: Add screenshots 27 | validations: 28 | required: true 29 | - type: checkboxes 30 | id: terms 31 | attributes: 32 | label: "Record" 33 | options: 34 | - label: I have checked the existing [issues](https://github.com/priyankarpal/ProjectsHut/issues) 35 | required: true 36 | 37 | - label: I have read the [Contributing Guidelines](https://github.com/priyankarpal/ProjectsHut/blob/main/contributing.md) 38 | required: true 39 | 40 | - label: I agree to follow this project's [Code of Conduct](https://github.com/priyankarpal/ProjectsHut/blob/main/CODE_OF_CONDUCT.md) 41 | required: true 42 | 43 | 44 | 45 | - label: I want to work on this issue 46 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/refactor_code.yml: -------------------------------------------------------------------------------- 1 | name: Refactor Code 🔧 2 | description: Use this label for code refactoring tasks. 3 | title: "[Refactor] " 4 | labels: ["🛠 goal: refactor", "🚦status: awaiting triage"] 5 | body: 6 | - type: input 7 | id: refactor_input 8 | attributes: 9 | label: File Name 10 | description: "Enter the file that you want to refactor in the codebase." 11 | placeholder: "For example - app/projects/page.tsx" 12 | validations: 13 | required: true 14 | - type: textarea 15 | id: refactor_description 16 | attributes: 17 | label: "Reason for Refactoring the Code" 18 | description: "Describe what improvements can be made in the codebase without introducing breaking changes." 19 | validations: 20 | required: true 21 | - type: checkboxes 22 | id: refactor_terms 23 | attributes: 24 | label: "Record" 25 | options: 26 | - label: I have checked the existing [issues](https://github.com/priyankarpal/ProjectsHut/issues) 27 | required: true 28 | 29 | - label: I have read the [Contributing Guidelines](https://github.com/priyankarpal/ProjectsHut/blob/main/contributing.md) 30 | required: true 31 | 32 | - label: I agree to follow this project's [Code of Conduct](https://github.com/priyankarpal/ProjectsHut/blob/main/CODE_OF_CONDUCT.md) 33 | required: true 34 | 35 | 36 | 37 | - label: I want to work on this issue 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yml: -------------------------------------------------------------------------------- 1 | name: 🐞 Bug Report 2 | description: File a bug report 3 | title: "Bug: " 4 | labels: ["🛠 goal: fix", "🚦status: awaiting triage", "💻 aspect: code"] 5 | body: 6 | - type: textarea 7 | id: what-happened 8 | attributes: 9 | label: What happened? 10 | placeholder: Add descriptions 11 | validations: 12 | required: true 13 | - type: textarea 14 | id: screenshots 15 | attributes: 16 | label: Add screenshots 17 | placeholder: Add screenshots 18 | validations: 19 | required: true 20 | - type: dropdown 21 | id: browsers 22 | attributes: 23 | label: What browsers are you seeing the problem on? 24 | multiple: true 25 | options: 26 | - Firefox 27 | - Chrome 28 | - Safari 29 | - Microsoft Edge 30 | - Brave 31 | - Other 32 | - type: checkboxes 33 | id: terms 34 | attributes: 35 | label: "Record" 36 | options: 37 | - label: I have checked the existing [issues](https://github.com/priyankarpal/ProjectsHut/issues) 38 | required: true 39 | 40 | - label: I have read the [Contributing Guidelines](https://github.com/priyankarpal/ProjectsHut/blob/main/contributing.md) 41 | required: true 42 | 43 | - label: I agree to follow this project's [Code of Conduct](https://github.com/priyankarpal/ProjectsHut/blob/main/CODE_OF_CONDUCT.md) 44 | required: true 45 | 46 | - label: I want to work on this issue 47 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | # name: Release Drafter 2 | 3 | # on: 4 | # push: 5 | # # branches to consider in the event; optional, defaults to all 6 | # branches: 7 | # - main 8 | # # pull_request event is required only for autolabeler 9 | # pull_request: 10 | # # Only following types are handled by the action, but one can default to all as well 11 | # types: [opened, reopened, synchronize] 12 | # # pull_request_target event is required for autolabeler to support PRs from forks 13 | # # pull_request_target: 14 | # # types: [opened, reopened, synchronize] 15 | 16 | # permissions: 17 | # contents: read 18 | 19 | # jobs: 20 | # update_release_draft: 21 | # permissions: 22 | # # write permission is required to create a github release 23 | # contents: write 24 | # # write permission is required for autolabeler 25 | # # otherwise, read permission is required at least 26 | # pull-requests: write 27 | # runs-on: ubuntu-latest 28 | # steps: 29 | # # (Optional) GitHub Enterprise requires GHE_HOST variable set 30 | # #- name: Set GHE_HOST 31 | # # run: | 32 | # # echo "GHE_HOST=${GITHUB_SERVER_URL##https:\/\/}" >> $GITHUB_ENV 33 | 34 | # # Drafts your next Release notes as Pull Requests are merged into "master" 35 | # - uses: release-drafter/release-drafter@v5 36 | # # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml 37 | # # with: 38 | # # config-name: my-config.yml 39 | # # disable-autolabeler: true 40 | # env: 41 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 42 | -------------------------------------------------------------------------------- /components/MobileNavbar.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { AiFillHome } from "react-icons/ai"; 3 | import { MdExplore } from "react-icons/md"; 4 | import { BiSolidBookBookmark } from "react-icons/bi"; 5 | import { FaGithub } from "react-icons/fa"; 6 | import Link from "next/link"; 7 | 8 | interface NavbarItem { 9 | icon: React.ReactElement; 10 | text: string; 11 | url: string; 12 | } 13 | 14 | const navbarItemsData: NavbarItem[] = [ 15 | { 16 | icon: , 17 | text: "Home", 18 | url: "/", 19 | }, 20 | { 21 | icon: , 22 | text: "Projects", 23 | url: "/projects", 24 | }, 25 | { 26 | icon: , 27 | text: "Docs", 28 | url: "/docs", 29 | }, 30 | { 31 | icon: , 32 | text: "GitHub", 33 | url: "https://github.com/priyankarpal/ProjectsHut", 34 | }, 35 | ]; 36 | 37 | export const MobileNavBar = () => { 38 | return ( 39 |
40 |
41 | {navbarItemsData.map((link, idx) => ( 42 | 43 |
44 | {link.icon} 45 |
{link.text}
46 |
47 | 48 | ))} 49 |
50 |
51 | ); 52 | }; 53 | -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Footer, Navbar, ScrollToTop } from "@/components"; 2 | import { MobileNavBar } from "@/components/MobileNavbar"; 3 | import "@/public/manifest.json"; 4 | import { Metadata } from "next"; 5 | import { Inter } from "next/font/google"; 6 | import "./globals.css"; 7 | 8 | const inter = Inter({ subsets: ["latin"] }); 9 | 10 | export const metadata: Metadata = { 11 | metadataBase: new URL("https://projectshut.vercel.app/"), 12 | manifest: "/manifest.json", 13 | title: { 14 | default: "ProjectsHut - Learn. Build. Share.", 15 | template: "%s - ProjectsHut", 16 | }, 17 | description: 18 | "A platform where you can share your open source projects with the world.", 19 | keywords: [ 20 | "ProjectHut", 21 | "projects", 22 | "educational resources", 23 | "wide range of products", 24 | "high-quality projects", 25 | "React", 26 | "Nodejs", 27 | "JavaScript", 28 | "open source", 29 | "contribution", 30 | "learners", 31 | ], 32 | authors: { name: "Priyankar Pal" }, 33 | openGraph: { 34 | title: "ProjectsHut - Learn. Build. Share.", 35 | description: 36 | "A platform where you can share your open source projects with the world.", 37 | url: "https://projectshut.vercel.app", 38 | siteName: "ProjectHut", 39 | locale: "en-US", 40 | type: "website", 41 | }, 42 | robots: { 43 | index: true, 44 | follow: true, 45 | googleBot: { 46 | index: true, 47 | follow: true, 48 | "max-video-preview": -1, 49 | "max-image-preview": "large", 50 | "max-snippet": -1, 51 | }, 52 | }, 53 | twitter: { 54 | title: "ProjectsHut - Learn. Build. Share.", 55 | card: "summary_large_image", 56 | description: 57 | "A platform where you can share your open source projects with the world.", 58 | images: 59 | "https://user-images.githubusercontent.com/88102392/251507361-e71396f9-92c6-4664-b7e4-4275cb902e65.png", 60 | }, 61 | }; 62 | 63 | export default function RootLayout({ 64 | children, 65 | }: { 66 | children: React.ReactNode; 67 | }) { 68 | return ( 69 | 70 | 71 | 72 | 73 | {children} 74 | 75 | 76 | 77 |