Showing preview only (952K chars total). Download the full file or copy to clipboard to get everything.
Repository: HimanshuNarware/Devlabs
Branch: main
Commit: 862f874132f3
Files: 171
Total size: 899.1 KB
Directory structure:
gitextract_wq4xmcei/
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── adding-new-tool.yml
│ │ ├── bug_report.yml
│ │ ├── documentation_update.yml
│ │ └── feature_request.yml
│ ├── pull_request_template.md
│ └── workflows/
│ ├── auto-comment-on-pr-merge.yml
│ ├── check_duplicate_tools.yml
│ ├── close-old-pr-woc.yml
│ ├── close-on-merge.yml
│ ├── greetings.yaml
│ ├── greetings.yml
│ └── restrict_pr.yml
├── .idea/
│ ├── .gitignore
│ ├── Devlabs-copy.iml
│ ├── Devlabs.iml
│ ├── modules.xml
│ └── vcs.xml
├── .vscode/
│ └── settings.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── README.md
├── backend/
│ ├── .dockerignore
│ ├── .gitignore
│ ├── Dockerfile
│ ├── init/
│ │ └── sampleToolsData.js
│ ├── package.json
│ ├── readme.md
│ ├── server.js
│ ├── src/
│ │ ├── app.js
│ │ ├── config/
│ │ │ ├── ExpressError.js
│ │ │ ├── database.js
│ │ │ └── nodemailer.js
│ │ ├── controllers/
│ │ │ ├── openSourceController.js
│ │ │ ├── specialController.js
│ │ │ ├── toolController.js
│ │ │ └── userController.js
│ │ ├── models/
│ │ │ ├── OpenSource.js
│ │ │ ├── Tool.js
│ │ │ ├── User.js
│ │ │ └── reviewForm.js
│ │ └── routes/
│ │ ├── openSource.js
│ │ ├── special.js
│ │ ├── tools.js
│ │ └── user.js
│ └── vercel.json
├── docker-compose.yaml
├── frontend/
│ ├── .dockerignore
│ ├── .gitignore
│ ├── Dockerfile
│ ├── package.json
│ ├── public/
│ │ ├── index.html
│ │ ├── manifest.json
│ │ └── robots.txt
│ └── src/
│ ├── App.css
│ ├── App.js
│ ├── ChatAssistant/
│ │ ├── Avatar.jsx
│ │ ├── ChatAssistant.css
│ │ ├── ChatAssistant.jsx
│ │ └── UserAvatar.jsx
│ ├── ChatBot/
│ │ ├── ActionProvider.jsx
│ │ ├── MessageParser.jsx
│ │ └── config.jsx
│ ├── Component/
│ │ ├── About.js
│ │ ├── BackToTopButton.js
│ │ ├── BookMark.js
│ │ ├── Contact.jsx
│ │ ├── Faq.js
│ │ ├── Footer.js
│ │ ├── Home.js
│ │ ├── Login.css
│ │ ├── Login.js
│ │ ├── Modal.js
│ │ ├── Navbar/
│ │ │ ├── Navbar.js
│ │ │ ├── NavbarCenter.js
│ │ │ ├── NavbarItem.js
│ │ │ ├── NavbarLeft.js
│ │ │ ├── NavbarRight.js
│ │ │ └── Progress.js
│ │ ├── NotFound.js
│ │ ├── OpenSource.js
│ │ ├── Pagination.js
│ │ ├── Preloader.js
│ │ ├── PrivacyPolicy.css
│ │ ├── PrivacyPolicy.js
│ │ ├── Profile.js
│ │ ├── Rate.css
│ │ ├── Rate.jsx
│ │ ├── Rateus.js
│ │ ├── Register.css
│ │ ├── Register.js
│ │ ├── Review.js
│ │ ├── ScrollToTop.jsx
│ │ ├── Sidebar/
│ │ │ ├── Sidebar.js
│ │ │ └── SidebarContent.js
│ │ ├── Signup.js
│ │ ├── TermsOfService.css
│ │ ├── TermsOfService.js
│ │ ├── TrailingCursor/
│ │ │ ├── TrailingCursor.jsx
│ │ │ ├── TrailingCursor.module.css
│ │ │ └── index.js
│ │ └── accordion.js
│ ├── DB/
│ │ ├── openSource.json
│ │ └── product.json
│ ├── Data.js
│ ├── Slice/
│ │ └── DataSlice.js
│ ├── Store/
│ │ └── store.js
│ ├── index.css
│ ├── index.js
│ ├── lottie/
│ │ ├── bookmark.json
│ │ ├── contact.json
│ │ └── pre.json
│ ├── pages/
│ │ ├── AI.jsx
│ │ ├── BackendTools.jsx
│ │ ├── CodingPlatform.jsx
│ │ ├── Collaboration.jsx
│ │ ├── CoursesPlatform.jsx
│ │ ├── EthicalHacking.jsx
│ │ ├── Extension.jsx
│ │ ├── Extensions.jsx
│ │ ├── FrontendTools.jsx
│ │ ├── Movie.jsx
│ │ ├── Movies.jsx
│ │ ├── Productivity.jsx
│ │ ├── RemoteJob.jsx
│ │ ├── RemoteJobs.jsx
│ │ ├── Testimonials.jsx
│ │ ├── UI.jsx
│ │ └── UserInterface.jsx
│ ├── style/
│ │ ├── AI.css
│ │ ├── About.css
│ │ ├── Animations.css
│ │ ├── BackToTopButton.css
│ │ ├── BackendTools.css
│ │ ├── BookMark.css
│ │ ├── CodingPlatform.css
│ │ ├── Collaboration.css
│ │ ├── Contact.css
│ │ ├── Courses.css
│ │ ├── EthicalHacking.css
│ │ ├── Extension.css
│ │ ├── Extensions.css
│ │ ├── Footer.css
│ │ ├── FrontendTools.css
│ │ ├── Home.css
│ │ ├── Modal.css
│ │ ├── Movie.css
│ │ ├── Movies.css
│ │ ├── Navbar.css
│ │ ├── NotFound.css
│ │ ├── OpenSource.css
│ │ ├── Pagination.css
│ │ ├── Productivity.css
│ │ ├── Profile.css
│ │ ├── Rateus.css
│ │ ├── RemoteJobs.css
│ │ ├── Remotejob.css
│ │ ├── Review.css
│ │ ├── Sidebar.css
│ │ ├── Signup.css
│ │ ├── Testimonials.module.css
│ │ ├── Typography.css
│ │ ├── UI.css
│ │ ├── UserInterface.css
│ │ ├── alert.css
│ │ ├── faq.css
│ │ ├── preloader.css
│ │ └── tooltip.css
│ └── utils/
│ └── paginationData.js
├── learn.md
└── package.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
================================================
FILE: .github/ISSUE_TEMPLATE/adding-new-tool.yml
================================================
name: 🛠️ Adding New Tool
description: Want to add new tool on the Devlabs
title: "[New Tool]: "
body:
- type: checkboxes
id: existing-issue
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists related to this new tool.
options:
- label: I have searched the existing issues
required: true
- type: textarea
id: Tool-description
attributes:
label: New Tool Description
description: Please provide a detailed description of the tool you wanna add.
placeholder: "Describe the new tool or enhancement you'd like to see."
validations:
required: true
- type: textarea
id: use-case
attributes:
label: Use Case
description: How would this tool enhance your use of the project?
placeholder: Describe a specific use case or scenario where this tool would be beneficial.
validations:
required: true
- type: textarea
id: benefits
attributes:
label: Benefits
description: What benefits would this tool bring to the project or community?
placeholder: Explain the advantages of implementing this new tool.
- type: textarea
id: screenShots
attributes:
label: Add ScreenShots
description: If any...
- type: dropdown
id: priority
attributes:
label: Priority
description: How important is this new tool to you?
options:
- High
- Medium
- Low
default: 0
validations:
required: true
- type: checkboxes
id: terms
attributes:
label: Record
options:
- label: "I have read the Contributing Guidelines"
required: true
- label: "I'm a GSSOC'24 contributor"
required: true
- label: "I have starred the repository"
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug report 🐞
description: File a bug report
title: "[Bug]: "
body:
- type: checkboxes
id: existing-issue
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the bug you encountered.
options:
- label: I have searched the existing issues
required: true
- type: textarea
id: what-happened
attributes:
label: Describe the bug
description: A concise description of what you are experiencing.
placeholder: Tell us what you see!
validations:
required: true
- type: textarea
id: expected-behaviour
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Add ScreenShots
description: Add sufficient ScreenShots to explain your issue.
- type: dropdown
id: browsers
attributes:
label: What browsers are you seeing the problem on?
multiple: true
options:
- Firefox
- Chrome
- Safari
- Microsoft Edge
- type: checkboxes
id: terms
attributes:
label: Record
options:
- label: "I have read the Contributing Guidelines"
required: true
- label: "I'm a GSSOC'24 contributor"
required: true
- label: "I have starred the repository"
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/documentation_update.yml
================================================
name: 📝 Documentation Update
description: Improve Documentation
title: "[Documentation Update]: "
body:
- type: checkboxes
id: existing-issue
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the updates you want to make.
options:
- label: I have searched the existing issues
required: true
- type: textarea
id: issue-description
attributes:
label: Issue Description
description: Please provide a clear description of the documentation update you are suggesting.
placeholder: Describe the improvement or correction you'd like to see in the documentation.
validations:
required: true
- type: textarea
id: suggested-change
attributes:
label: Suggested Change
description: Provide details of the proposed change to the documentation.
placeholder: Explain how the documentation should be updated or corrected.
validations:
required: true
- type: textarea
id: rationale
attributes:
label: Rationale
description: Why is this documentation update necessary or beneficial?
placeholder: Explain the importance or reasoning behind the suggested change.
validations:
required: False
- type: dropdown
id: urgency
attributes:
label: Urgency
description: How urgently do you believe this documentation update is needed?
options:
- High
- Medium
- Low
default: 0
validations:
required: true
- type: checkboxes
id: terms
attributes:
label: Record
options:
- label: "I have read the Contributing Guidelines"
required: true
- label: "I'm a GSSOC'24 contributor"
required: true
- label: "I have starred the repository"
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: ✨ Feature Request
description: Suggest a feature
title: "[Feature Request]: "
body:
- type: checkboxes
id: existing-issue
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for this feature.
options:
- label: I have searched the existing issues
required: true
- type: textarea
id: feature-description
attributes:
label: Feature Description
description: Please provide a detailed description of the feature you are requesting.
placeholder: Describe the new feature or enhancement you'd like to see.
validations:
required: true
- type: textarea
id: use-case
attributes:
label: Use Case
description: How would this feature enhance your use of the project?
placeholder: Describe a specific use case or scenario where this feature would be beneficial.
validations:
required: true
- type: textarea
id: benefits
attributes:
label: Benefits
description: What benefits would this feature bring to the project or community?
placeholder: Explain the advantages of implementing this feature.
- type: textarea
id: screenShots
attributes:
label: Add ScreenShots
description: If any...
- type: dropdown
id: priority
attributes:
label: Priority
description: How important is this feature to you?
options:
- High
- Medium
- Low
default: 0
validations:
required: true
- type: checkboxes
id: terms
attributes:
label: Record
options:
- label: "I have read the Contributing Guidelines"
required: true
- label: "I'm a GSSOC'24 contributor"
required: true
- label: "I have starred the repository"
required: true
================================================
FILE: .github/pull_request_template.md
================================================
## Related Issue
[Cite any related issue(s) this pull request addresses. If none, simply state "None”]
## Description
[Please include a brief description of the changes or features added]
## Type of PR
- [ ] Bug fix
- [ ] Feature enhancement
- [ ] Documentation update
- [ ] Other (specify): _______________
## Screenshots / videos (if applicable)
[Attach any relevant screenshots or videos demonstrating the changes]
## Checklist:
- [ ] I have performed a self-review of my code
- [ ] I have read and followed the Contribution Guidelines.
- [ ] I have tested the changes thoroughly before submitting this pull request.
- [ ] I have provided relevant issue numbers, screenshots, and videos after making the changes.
- [ ] I have commented my code, particularly in hard-to-understand areas.
<!-- [X] - put a cross/X inside [] to check the box -->
## Additional context:
[Include any additional information or context that might be helpful for reviewers.]
================================================
FILE: .github/workflows/auto-comment-on-pr-merge.yml
================================================
# @format
name: Auto Comment on PR Merge
on:
pull_request:
types: [closed]
jobs:
comment:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Add Comment to Merged PR
env:
TOKEN: ${{ secrets.TOKEN }}
run: |
curl -H "Authorization: token $TOKEN" \
-X POST \
-d '{"body":"🎉 Your pull request has been successfully merged! 🎉 Thank you for your contribution to our project. Your efforts are greatly appreciated. Keep up the fantastic work! 🚀"}' \
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments"
================================================
FILE: .github/workflows/check_duplicate_tools.yml
================================================
# @format
name: Check for Duplicates and Close Issues on PR Merge
on:
pull_request:
types: [opened, synchronize, closed]
jobs:
check-duplicates:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Check for duplicate entries in product.json
run: |
# Check for duplicate entries based on the 'link' field in product.json
jq -r '.[].link' product.json | sort | uniq -d > duplicates.txt
if [ -s duplicates.txt ]; then
echo "Duplicate entries found in product.json based on 'link':"
cat duplicates.txt
exit 1
else
echo "No duplicate entries found based on 'link'."
fi
close-issues:
runs-on: ubuntu-latest
needs: check-duplicates
if: github.event.pull_request.merged == true
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Close linked issues
run: |
ISSUES=$(jq -r '.pull_request.body' "$GITHUB_EVENT_PATH" | grep -Eo '#[0-9]+' | tr -d '#')
for ISSUE in $ISSUES
do
echo "Closing issue #$ISSUE"
curl -X POST -H "Authorization: token ${{ secrets.TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/issues/$ISSUE/comments \
-d '{"body":"Closed by PR #${{ github.event.pull_request.number }}"}'
curl -X PATCH -H "Authorization: token ${{ secrets.TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/issues/$ISSUE \
-d '{"state":"closed"}'
done
================================================
FILE: .github/workflows/close-old-pr-woc.yml
================================================
# @format
name: Close Stale PRs
on:
schedule:
- cron: '0 0 * * *' # Runs daily at midnight
pull_request:
types:
- opened
- reopened
- synchronize
permissions:
pull-requests: write
issues: write
jobs:
close_stale_prs:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/stale@v7
with:
repo-token: ${{ secrets.TOKEN }}
stale-pr-message: 'This PR has been automatically closed due to inactivity from the owner for 15 days.'
days-before-pr-stale: 15
days-before-pr-close: 0
exempt-pr-author: false
exempt-pr-labels: ''
only-labels: ''
operations-per-run: 30
remove-stale-when-updated: true
debug-only: false
================================================
FILE: .github/workflows/close-on-merge.yml
================================================
# @format
name: Close Issues on PR Merge
on:
pull_request:
types: [closed]
jobs:
close-issues:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Close linked issues
if: github.event.pull_request.merged == true
run: |
ISSUES=$(jq -r '.pull_request.body' "$GITHUB_EVENT_PATH" | grep -Eo '#[0-9]+' | tr -d '#')
for ISSUE in $ISSUES
do
echo "Closing issue #$ISSUE"
curl -X POST -H "Authorization: token ${{ secrets.TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/issues/$ISSUE/comments \
-d '{"body":"Closed by PR #${{ github.event.pull_request.number }}"}'
curl -X PATCH -H "Authorization: token ${{ secrets.TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/issues/$ISSUE \
-d '{"state":"closed"}'
done
================================================
FILE: .github/workflows/greetings.yaml
================================================
# @format
name: Greetings
on: [pull_request_target, issues]
jobs:
greeting:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.TOKEN }}
issue-message: 'Hi there! Thanks for opening this issue. We appreciate your contribution to this open-source project. We aim to respond or assign your issue as soon as possible.'
pr-message: 'Welcome to Our repository.🎊 Thank you so much for taking the time to point this out.'
================================================
FILE: .github/workflows/greetings.yml
================================================
# @format
name: 'Greetings'
on:
fork:
push:
branches: [main]
issues:
types: [opened]
pull_request_target:
types: [opened]
jobs:
welcome:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: EddieHubCommunity/gh-action-community/src/welcome@main
with:
github-token: ${{ secrets.TOKEN }}
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!
pr-message: |
Great job, @${{ github.actor }}! 🎉 Thank you for submitting your pull request. Your contribution is valuable and we appreciate your efforts to improve our project.
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/HimanshuNarware/Devlabs/blob/main/CONTRIBUTING.md)'
================================================
FILE: .github/workflows/restrict_pr.yml
================================================
# @format
name: Restrict Contributor to limited contributions in Devlabs
on:
pull_request_target:
types:
- opened
jobs:
evaluate_and_close:
runs-on: ubuntu-latest
steps:
- name: Check merged pull requests and calculate score
id: calculate_score
uses: actions/github-script@v4
with:
github-token: ${{ secrets.TOKEN }}
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const pullRequestOpener = context.payload.pull_request.user.login;
let mergedPullRequests = [];
let page = 1;
let perPage = 100;
let response;
do {
response = await github.pulls.list({
owner,
repo,
state: 'closed',
per_page: perPage,
page: page
});
mergedPullRequests = mergedPullRequests.concat(response.data.filter(pr => pr.user.login === pullRequestOpener && pr.merged_at !== null));
page++;
} while (response.data.length === perPage);
let score = 0;
let prDetails = [];
const scoreMap = {
'level3': 45,
'level2': 25,
'level1': 10
};
for (const pr of mergedPullRequests) {
let prScore = 0;
let labelsWithScores = [];
for (const label of pr.labels) {
if (scoreMap[label.name]) {
prScore += scoreMap[label.name];
labelsWithScores.push(`${label.name} score: (${scoreMap[label.name]})`);
}
}
score += prScore;
if (labelsWithScores.length > 0) {
prDetails.push(`- [#${pr.number}](${pr.html_url}) with labels: ${labelsWithScores.join(', ')}`);
}
}
const threshold = 150;
console.log(`User score: ${score}`);
console.log(`Score threshold: ${threshold}`);
if (score >= threshold) {
const comment = `Hey @${pullRequestOpener}, You have reached your limit to contribute in Devlabs with a score of ${score}. \n We believe in giving equal opportunity to everyone so you will not be able to contribute to Devlabs now onwards. 💗 \n Thank you for your valuable time and contribution in Devlabs 🕹️! \n\n Your merged pull requests:\n${prDetails.join('\n')}`;
core.exportVariable('comment_body', comment);
core.setOutput('close_pull_request', true);
} else {
core.exportVariable('comment_body', '');
core.setOutput('close_pull_request', false);
}
- name: Add spam label and close the pull request
if: always() && steps.calculate_score.outputs.close_pull_request == 'true'
uses: actions/github-script@v4
with:
github-token: ${{ secrets.TOKEN }}
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const pullRequestNumber = context.payload.pull_request.number;
const comment = process.env.comment_body;
if (comment.trim() === '') {
console.log('Comment body is empty. Skipping comment creation.');
return;
}
await github.issues.createComment({
owner,
repo,
issue_number: pullRequestNumber,
body: comment
});
await github.issues.addLabels({
owner,
repo,
issue_number: pullRequestNumber,
labels: ['spam🚨']
});
await github.pulls.update({
owner,
repo,
pull_number: pullRequestNumber,
state: 'closed'
});
================================================
FILE: .idea/.gitignore
================================================
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
================================================
FILE: .idea/Devlabs-copy.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
================================================
FILE: .idea/Devlabs.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
================================================
FILE: .idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Devlabs.iml" filepath="$PROJECT_DIR$/.idea/Devlabs.iml" />
</modules>
</component>
</project>
================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
================================================
FILE: .vscode/settings.json
================================================
{
"git.ignoreLimitWarning": true,
"emmet.includeLanguages": {
"\"javascript\":": "\"javascriptreact\""
},
"C_Cpp.errorSquiggles": "disabled",
"deepscan.enable": true
}
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Devlabs Code of Conduct
We, the maintainers and contributors of Devlabs, are committed to providing a friendly, safe, and inclusive environment for everyone who wants to participate in this project. We expect all participants to follow this Code of Conduct to ensure that our community is welcoming and harassment-free.
## Our Standards
- **Be Respectful:** Treat all community members with respect and kindness. Respect each other's opinions, experiences, and backgrounds, even if they differ from your own.
- **Be Inclusive:** Welcome people of all backgrounds, experiences, and perspectives. Discrimination, hate speech, and harassment will not be tolerated.
- **Be Collaborative:** Work together constructively. Disagreements can happen, but they should be resolved through respectful and constructive discussion.
- **Be Mindful of Your Language:** Be mindful of your words and actions. Avoid offensive or disrespectful comments and content.
- **No Trolling or Harassment:** Do not engage in trolling, bullying, or harassment, whether it's based on race, gender, sexual orientation, disability, religion, or any other personal characteristics.
- **Respect Privacy:** Do not share personal information of others without their explicit consent.
## Reporting Violations
If you witness or experience any behavior that violates this Code of Conduct, please report it to the project maintainers. All reports will be kept confidential, and we will take appropriate action to address the issue.
## Enforcement
Maintainers of Devlabs are responsible for enforcing this Code of Conduct. If someone engages in harmful behavior, maintainers may take action, ranging from a warning to temporary or permanent expulsion from the project.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
By participating in the Devlabs community, you agree to abide by this Code of Conduct. We look forward to your contributions and collaboration!
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to [Devlabs] 🚀
Thank you for considering contributing to [Devlabs]! We appreciate your interest in helping make this project better.
## Table of Contents
- [Contributing to \[Devlabs\]](#contributing-to-devlabs-)
- [Table of Contents](#table-of-contents)
- [Code of Conduct](#code-of-conduct)
- [How Can I Contribute?](#how-can-i-contribute)
- [Reporting Bugs](#reporting-bugs-)
- [Requesting Features](#requesting-features-)
- [Submitting Changes](#submitting-changes-)
- [Pull Request Guidelines](#pull-request-guidelines-)
- [Style Guide](#style-guide-)
- [License](#license-)
## Code of Conduct
This project and its community adhere to the [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report any unacceptable behavior to [project owner's email].
## How Can I Contribute? 🌟
### Reporting Bugs 🐛
If you come across a bug or an issue with [Devlabs], please take the following steps:
1. **Search** the [issue tracker](https://github.com/HimanshuNarware/Devlabs/issues) to check if the issue has already been reported. If it has, feel free to add any additional information or subscribe to the existing issue.
2. **Create a New Issue** if the issue hasn't been reported yet, with a descriptive title and a clear description of the problem. Include any relevant details such as operating system, browser version, and steps to reproduce the issue.
### Requesting Features ✨
If you have an idea for a new feature or improvement, please follow these steps:
1. **Search** the [issue tracker](https://github.com/HimanshuNarware/Devlabs/issues) to check if the feature request already exists. If it does, you can comment on the existing request to provide more information or express your interest.
2. **Create a New Issue** if the feature request doesn't exist, with a clear and concise title and a detailed description of the feature or enhancement you're proposing. Explain why it's valuable and how it aligns with the project's goals.
### Submitting Changes 🛠️
If you want to contribute code changes, follow these steps:
1. **Fork the repository** to your own GitHub account.
2. **Clone your forked repository** to your local machine.
```bash
git clone https://github.com/HimanshuNarware/Devlabs.git
```
3. **Create a new branch** for your changes.
```bash
git checkout -b feature/your-feature-name
```
4. **Make your changes**, following the [style guide](#style-guide) and ensuring that your code adheres to the project's coding standards.
5. **Commit your changes** with a descriptive commit message.
```bash
git commit -m "Add new feature: your feature name"
```
6. **Push your changes** to your forked repository on GitHub.
```bash
git push origin feature/your-feature-name
```
7. **Open a pull request (PR)** on the [original repository](https://github.com/HimanshuNarware/Devlabs) and provide a detailed description of your changes.
### Alternatively contribute using GitHub Desktop 🖥️
1. **Open GitHub Desktop**:
Launch GitHub Desktop and log in to your GitHub account if you haven't already.
2. **Clone the Repository**:
- If you haven't cloned the repository yet, you can do so by clicking on the "File" menu and selecting "Clone Repository."
- Choose the repository from the list of repositories on GitHub and clone it to your local machine.
3. **Switch to the Correct Branch**:
- Ensure you are on the branch that you want to submit a pull request for.
- If you need to switch branches, you can do so by clicking on the "Current Branch" dropdown menu and selecting the desired branch.
4. **Make Changes**:
Make your changes to the code or files in the repository using your preferred code editor.
5. **Commit Changes**:
- In GitHub Desktop, you'll see a list of the files you've changed. Check the box next to each file you want to include in the commit.
- Enter a summary and description for your changes in the "Summary" and "Description" fields, respectively. Click the "Commit to <branch-name>" button to commit your changes to the local branch.
6. **Push Changes to GitHub**:
After committing your changes, click the "Push origin" button in the top right corner of GitHub Desktop to push your changes to your forked repository on GitHub.
7. **Create a Pull Request**:
- Go to the GitHub website and navigate to your fork of the repository.
- You should see a button to "Compare & pull request" between your fork and the original repository. Click on it.
8. **Review and Submit**:
- On the pull request page, review your changes and add any additional information, such as a title and description, that you want to include with your pull request.
- Once you're satisfied, click the "Create pull request" button to submit your pull request.
9. **Wait for Review**:
Your pull request will now be available for review by the project maintainers. They may provide feedback or ask for changes before merging your pull request into the main branch of the repository.
### Pull Request Guidelines 📋
To ensure a smooth review process, please follow these guidelines when submitting a pull request:
- Your code should be well-documented and include clear comments where necessary.
- Run any relevant tests to ensure that your changes don't introduce new issues.
- Ensure your code follows the project's coding standards and style guide (see [Style Guide](#style-guide)).
- Keep your pull request focused on a single feature or bug fix.
- Provide a clear and concise title and description for your pull request.
## Style Guide 📚
[Devlabs] follows a specific coding style and structure. Please refer to the [style guide](STYLE_GUIDE.md) for details on code formatting, naming conventions, and other coding standards.
## License 📜
By contributing to [Devlabs], you agree that your contributions will be licensed under the project's [LICENSE](LICENSE.md).
================================================
FILE: README.md
================================================
<a id="top"></a>
<div align="center">
<h1><img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Objects/Laptop.png" alt="Laptop" width="50" height="50" /> DevLabs</h1>
<p>Welcome to DevLabs, a website where you can search for free tools that are useful for your daily needs. This application is created by the incredible open-source community. On DevLabs, you can discover a collection of free tools that can assist you in various aspects of your life. Moreover, you have the opportunity to contribute to this project by adding more tools to the database.</p>
<p>Check out the live project at <a href="https://DevLabs-one.vercel.app">DevLabs</a></p>
<img src="https://github.com/HimanshuNarware/Devlabs/assets/83147410/a508cf73-6724-46d3-a66d-6b9a7811bfdd" alt="DevLabs" />
</div>
---

## 🏆 Featured in:
<table>
<tr>
<th>Event Logo</th>
<th>Event Name</th>
<th>Event Description</th>
</tr>
<tr>
<td><img src="https://user-images.githubusercontent.com/63473496/213306279-338f7ce9-9a9f-4427-8c2a-3e344874498f.png#gh-dark-mode-only" width="200" height="auto" loading="lazy" alt="GSSoC 24"/></td>
<td>GirlScript Summer of Code 2024</td>
<td>GirlScript Summer of Code is a three-month-long Open Source Program conducted every summer by GirlScript Foundation. It is an initiative to bring more beginners to Open-Source Software Development.
</tr>
</table>
## 🌟 Our Mission
Our website provides a platform for contributors from all over the world to share their ideas in the form of helpful websites that are free to use. It helps us save a ton of time by allowing us to access a list of all the websites in one location. Whether it be a tool or an educational platform, we may discover any type of website here. This makes it a platform for sharing knowledge!
---
## 💻 Tech Stack
<!-- JavaScript -->
<img src="https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&logo=javascript&logoColor=%23F7DF1E" alt="JavaScript logo">
<!-- HTML5 -->
<img src="https://img.shields.io/badge/html5-%23E34F26.svg?style=for-the-badge&logo=html5&logoColor=white" alt="HTML5 logo">
<!-- CSS3 -->
<img src="https://img.shields.io/badge/css3-%231572B6.svg?style=for-the-badge&logo=css3&logoColor=white" alt="CSS3 logo">
<!-- React.js -->
<img src="https://img.shields.io/badge/react-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB" alt="React.js logo">
---
## 🚀 Quick Start
Contributions are welcome! If you have any ideas, suggestions, or bug fixes, please open an issue or submit a pull request. Make sure to follow the project's code of conduct.
---
<!-- Code of conduct -->
<div>
<h2><img src = "https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Hand%20gestures/Handshake.png" width="35" height="35"> Code of Conduct</h2>
</div>
Please note that this project is released with a [Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
## 📦 Installation
### With Docker
You can clone the project directly from this repo to your local system.
### 1. Clone the Repo
```bash
git clone https://github.com/username/Devlabs.git
```
### 2. Navigate to the project directory
```bash
cd Devlabs
```
### 3. Create Backend Environment
```bash
MONGODB_URI=<mongodb connection uri for the database>
PORT=<port number on which backend is running>
FRONTEND_URL=<url of the frontend>
MAIL=<email from which to send mail to self>
PASSWORD=<passkey corresponding to above mail>
```
### 4. Create Frontend Environment
All the environment variables for react must be prefixed with `REACT_APP_`.
```bash
REACT_APP_BACKEND=<url of the backend>
```
### 5. Run Docker Compose
```bash
docker-compose up --build
```
You have to use build for the first time only then you can use `docker-compose up`
Now follow all the steps from point 6 of without docker to contribute to the project.
### Without Docker
You can clone the project directly from this repo to your local system.
### 1. Clone the Repo
```bash
git clone https://github.com/username/Devlabs.git
```
### 2. Install Dependencies
```bash
npm install
```
### 3. Start Development Server
```bash
npm start
#or
npm run dev
```
### 4. Create Backend Environment
```bash
MONGODB_URI=<mongodb connection uri for the database>
PORT=<port number on which backend is running>
FRONTEND_URL=<url of the frontend>
MAIL=<email from which to send mail to self>
PASSWORD=<passkey corresponding to above mail>
```
### 5. Create Frontend Environment
All the environment variables for react must be prefixed with `REACT_APP_`.
```bash
REACT_APP_BACKEND=<url of the backend>
```
### 6. Create a New Branch
```bash
git checkout -b YourBranchName
```
### 7. Make Your Changes to the Source Code
To add a new tool:
> Go to **src > DB > `product.json`** & add your code
```bash
{
productName: "< App_Name >",
category: "remote | resume | tweet | ai | ethical | movies | extensions | tools",
image: "< Image-Url >",
link: "< Link_to_the_website >",
description: "< Description of product >"
},
```
- Ensure that your URLs are short. It is recommended to use bitly for URL shortening.
- Descriptions should not exceed 10-12 words.
### 8. Stage Your Changes
⚠️ **Make sure** not to commit `package.json` or `package-lock.json` file
⚠️ **Make sure** not to run the commands `git add .` or `git add *`
---
Instead, stage your changes for each file/folder specifically.
```bash
git add "<files_you_have_changed>"
```
### 9. Commit Your Changes
```bash
git commit -m "<your_commit_message>"
```
### 10. Push Your Local Commits to the Remote Repository
```bash
git push origin YourBranchName
```
### 11. Create a Pull Request
Create a [Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request)!
<div>
<h2><img src="https://github.com/Meetjain1/wanderlust/assets/133582566/90f3930e-5a12-4a4e-8ac9-0dc7d5396adb" width="35" height="35">Are Ready to Contribute?</h2>
</div>
If you would like to contribute to the project then kindly go through [Contributing Guidelines](CONTRIBUTING.md) to understand everything from setup to necessary instructions.
<div align="center">
<h2>Let's Collaborate and Make DevLabs Even Better! 💻🌟</h2>
</div>
<details>
<summary><h2>✨ Features</h2></summary>
1. User Authentication:
Secure user registration and login using JWT.
OAuth integration for social logins (Google, Facebook).
2. User Profiles:
Customizable user profiles.
Profile picture upload and bio section.
3. Tool Rating & Reviews
Users can rate and review tools.
Aggregate ratings for each tool displayed.
4. Favorites & Bookmarking
Users can bookmark their favorite tools.
Quick access to bookmarked tools from the profile.
5. Tool Categories & Tags
Tools categorized for easy browsing.
Tagging system for quick filtering and searching.
6. Advanced Search
Search tools by name, category, or tags.
Filter results by ratings and reviews.
7. Responsive Design
Fully responsive design for mobile, tablet, and desktop.
8. Notifications
Email notifications for new tools, reviews, and updates.
9. Admin Dashboard
Manage users, tools, and reviews.
Analytics on tool usage and user engagement.
10. Documentation
Comprehensive documentation for developers.
API documentation for integrating with other platforms.
### 📚 Learn
To know more about project, please go through [Learn](learn.md)
</details>
### 🌍 Community
<hr>
<h2 align = "center">Our Contributors ❤️</h2>
<div align = "center">
<h3>Thank you for contributing to our repository</h3>
<a href="https://github.com/HimanshuNarware/Devlabs/graphs/contributors">
<img src="https://contrib.rocks/image?repo=HimanshuNarware/Devlabs" />
</a>
</div>
<hr>
<div>
<h2><img src="https://fonts.gstatic.com/s/e/notoemoji/latest/1f64f_1f3fb/512.webp" width="35" height="35"> Support </h2>
</div>
<div>
Don't forget to leave a star<img src="https://fonts.gstatic.com/s/e/notoemoji/latest/1f31f/512.webp" width="35" height="30"> for this project!
</div> <br>
<a href="#top" style="position: fixed; bottom: 20px; right: 20px; background-color: black ; color: white; padding: 10px 20px; text-align: center; text-decoration: none; display: inline-block; border-radius: 5px; font-family: Arial; font-size: 16px;">Go to Top</a>
`
================================================
FILE: backend/.dockerignore
================================================
node_modules
build
.DS_Store
.env
.git
.gitignore
================================================
FILE: backend/.gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# production
/build
# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
config.env
.vscode
npm-debug.log*
yarn-debug.log*
yarn-error.log*
================================================
FILE: backend/Dockerfile
================================================
FROM node:alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
EXPOSE 8000
CMD ["npm", "start"]
================================================
FILE: backend/init/sampleToolsData.js
================================================
const mongoose = require("mongoose");
const { connectToDB } = require("../src/config/database");
const Tool = require("../src/models/Tool");
async function db() {
try {
await connectToDB();
console.log("Database connected!");
const sampleData = [
{
productName: "Carousel Hero",
category: "tools",
image: "https://i.ibb.co/7rRW6TW/logo-social-large.png",
link: "https://carouselhero.com",
description: "Create social media carousels for free and with no signup.",
},
{
productName: "PikaShows",
category: "movies",
image: "https://tinyurl.com/37csr8my",
link: "https://www.pikashows.download/",
description: "Download this application for PC and Mobile to stream all types of TV Shows and Movies.",
},
{
productName: "Scaler",
category: "coding",
image: "https://bit.ly/3XoZKgc",
link: "https://bit.ly/3plUFZw",
description: "Scaler is an outcome-focused, ed-tech platform for techies.",
},
{
productName: "InterviewBit",
category: "coding",
image: "https://bit.ly/3NH8dIt",
link: "https://bit.ly/43VBwNf",
description: "InterviewBit prepares you not only for the interviews, but for the actual job too.",
},
{
productName: "Momentum",
category: "extensions",
image: "https://bit.ly/3JoG8mI",
link: "https://bit.ly/3JoG6v6",
description: "Replace new tab page with a personal dashboard to help you get focused, stay organized, and keep motivated to achieve your goals.",
},
{
productName: "ACM",
category: "tools",
image: "https://avatars.githubusercontent.com/u/65459277?s=200&v=4",
link: "https://www.acm.org/",
description: "It provides a platform for computing professionals, researchers, educators, and students to exchange ideas and information related to computer science and information technology.",
},
];
const insertedData = await Tool.insertMany(sampleData);
console.log("Sample data added successfully!", insertedData);
} catch (error) {
console.error("Error adding sample data:", error);
} finally {
mongoose.connection.close(() => {
console.log("Database connection closed.");
});
}
}
db();
================================================
FILE: backend/package.json
================================================
{
"name": "devlabs-backend",
"version": "1.0.0",
"description": "A backend for storing data for devlabs web-application",
"main": "server.js",
"scripts": {
"start": "node server.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.2",
"mongoose": "^7.6.3",
"nodemailer": "^6.9.7",
"password-hash": "^1.2.2"
}
}
================================================
FILE: backend/readme.md
================================================
# DevLabs Backend
Welcome to the backend of DevLabs, the platform that connects users with a collection of free tools from the open-source community. This backend repository powers the server-side logic and facilitates seamless interactions with the database.
## Tech Stack
- Node.js - A JavaScript runtime for server-side development.
- Express.js - A minimal and flexible Node.js web application framework.
- MongoDB - A NoSQL database for storing tool data.
- Mongoose - An ODM (Object Data Modeling) library for MongoDB and Node.js.
## Installation
1. Clone the repository:
```bash
git clone https://github.com/username/Devlabs-backend.git
### 2. Install Dependencies
```bash
npm install
`
### 3. Start development Server
```bash
npm start
```
### 3. Create Backend Environment
```bash
MONGODB_URI=<mongodb connection uri for the database>
PORT=<port number on which backend is running>
FRONTEND_URL=<url of the frontend>
MAIL=<email from which to send mail to self>
PASSWORD=<passkey corresponding to above mail>
```
### 4. Create Frontend Environment
All the environment variables for react must be prefixed with `REACT_APP_`.
```bash
REACT_APP_BACKEND=<url of the backend>
```
### 5 Create a new branch
```bash
git checkout -b YourBranchName
```
### 6. Make your changes to the source code
Add new tool :
> Go to **src > DB > `product.json`** & add your code
```bash
{
productName: "< App_Name >",
category: "remote | resume | tweet | ai | ethical | movies | extensions | tools",
image: "< Image-Url >",
link: "< Link_to_the_website >",
description: "< Description of product >"
},
```
To ensure that your URLs are short, it is recommended to use bitly for URL shortening.
Description should not exceed 10-12 words
### 7. Stage your changes
⚠️ **Make sure** not to commit `package.json` or `package-lock.json` file
⚠️ **Make sure** not to run the commands `git add .` or `git add *`
> Instead, stage your changes for each file/folder
>
> By using public path it means it will add all files and folders under that folder, it is better to be specific
```bash
git add "<files_you_have_changed>"
```
### 8. Commit your changes
```bash
git commit -m "<your_commit_message>"
```
### 9. Push your local commits to the remote repository
```bash
git push origin YourBranchName
```
**10.** Create a [Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request)!
================================================
FILE: backend/server.js
================================================
const app = require("./src/app");
const { connectToDB } = require("./src/config/database");
const port = process.env.PORT || 8000;
app.listen(port, async () => {
await connectToDB();
console.log(`Application running on http://localhost:${port}\n`);
})
================================================
FILE: backend/src/app.js
================================================
const bodyParser = require("body-parser");
const cors = require("cors");
const express = require("express");
const app = express();
require("dotenv").config();
app.use("/public", express.static("public"));
app.use(bodyParser.json({ limit: "50mb" }));
app.use(bodyParser.urlencoded({ extended: true, limit: "50mb" }));
app.use(
cors({
origin: 'http://localhost:3000',
credentials: true,
})
);
app.get("/", async (req, res) => {
return res.status(200).json({ message: "Welcome to DevLabs Backend!" });
});
app.use("/special", require("./routes/special"));
app.use("/tools", require("./routes/tools"));
app.use("/open-source", require("./routes/openSource"));
app.use("/users", require("./routes/user"));
module.exports = app;
================================================
FILE: backend/src/config/ExpressError.js
================================================
class ExpressError extends Error{
constructor(status,message){
super()
this.status = status
this.message = message
}
}
module.exports = ExpressError
================================================
FILE: backend/src/config/database.js
================================================
const mongoose = require("mongoose");
require("dotenv").config();
const DB_URI = process.env.MONGODB_URI || "mongodb://0.0.0.0:27017"
const connectToDB = async () => {
try {
await mongoose.connect(DB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
console.log("Connected to MongoDB !");
}
catch (error) {
console.log("MongoDB Connection Error");
console.log(error);
}
}
module.exports = {connectToDB};
================================================
FILE: backend/src/config/nodemailer.js
================================================
const nodemailer = require("nodemailer");
require("dotenv").config();
const transporter = nodemailer.createTransport({
service: "gmail",
auth:{
user: process.env.EMAIL,
pass: process.env.PASSWORD
}
});
const mailOptions = (email) => {
return {
from: process.env.EMAIL,
to: email,
bcc: process.env.EMAIL
};
};
module.exports = {transporter, mailOptions}
================================================
FILE: backend/src/controllers/openSourceController.js
================================================
const OpenSource = require("../models/OpenSource");
require("dotenv").config();
const addProject = async (req, res) => {
try {
const { projectName, ownerUsername, tags, link, description } = req.body;
// Validation
if (!projectName || !ownerUsername || !link || !description) {
return res.status(400).json({ success: false, errors: ["All fields are required"] });
}
const newProject = new OpenSource({
projectName, ownerUsername, tags, link, description
});
await newProject.save();
return res.status(201).json({ success: true, project: newProject });
} catch (error) {
console.error(error);
return res.status(500).json({ success: false, errors: ["Internal Server Error"] });
}
};
const fetchAllProjects = async (req, res) => {
try {
const { page = 1, limit = 10 } = req.query;
const openSourceProjects = await OpenSource.find()
.skip((page - 1) * limit)
.limit(parseInt(limit));
const totalProjects = await OpenSource.countDocuments();
return res.status(200).json({
success: true,
openSourceProjects,
totalPages: Math.ceil(totalProjects / limit),
currentPage: parseInt(page)
});
} catch (error) {
console.error(error);
return res.status(500).json({ success: false, errors: ["Internal Server Error"] });
}
};
module.exports = { addProject, fetchAllProjects };
================================================
FILE: backend/src/controllers/specialController.js
================================================
const mongoose = require("mongoose")
const reviewForm = require("../models/reviewForm");
const {transporter, mailOptions} = require("../config/nodemailer");
const capitalize = (word) => {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}
const generateEmailText = (data) => {
const text = Object.entries(data).reduce((str, [key, value]) => {
return str += `${capitalize(key)}: \n${value}\n\n`;
}, "");
return text;
}
const generateEmailBody = ({name, email, review}) => {
const html = `
<html>
<body>
<h2>Message from ${name}</h2>
<p><strong>Email:</strong> ${email}</p>
<span><strong>Message:</strong></span>
<p>${review}</p>
</body>
</html>
`;
return html;
}
const sendMail = async (req, res) => {
try{
const { name, email, review } = req.body;
if (!name || !email || !review)
return res.status(400).json({ success:false, errors: ["Missing Data"] });
await transporter.sendMail({
...mailOptions(email),
subject: `${name} CONTACTING THROUGH PORTFOLIO`,
text: generateEmailText({ name, email, review }),
html: generateEmailBody({ name, email, review })
});
const newReview = new reviewForm({
name,
email,
msg: review,
});
console.log(newReview)
try {
await newReview.save();
//console.log("SAVED DATA")
} catch (error) {
//console.log("ERROR IS SAVING DATA")
}
return res.status(200).json({ success: true });
}
catch (error) {
console.log(error);
return res.status(500).json({ success: false, errors: ["Internal Server Error"] });
}
};
module.exports = { sendMail };
================================================
FILE: backend/src/controllers/toolController.js
================================================
const Tool = require("../models/Tool");
require("dotenv").config();
const addTool = async (req, res) => {
try {
const {productName, category, image, link, description} = req.body;
const newTool = await Tool.create({
productName, category, image, link, description
})
if (!newTool)
return res.statsu(401).json({ success: false, errors: ["Issue Adding the Tool"] });
return res.status(201).json({ success: true });
}
catch (error) {
console.log(error);
return res.status(500).json({ success: false, errors: ["Internal Server Error"] });
}
}
const fetchAllTools = async (req, res) => {
try{
const tools = await Tool.find();
return res.status(200).json({ success: true, tools: tools });
}
catch (error) {
console.log(error);
return res.status(500).json({ success: false, errors: ["Internal Server Error"] });
}
}
module.exports = { addTool, fetchAllTools };
================================================
FILE: backend/src/controllers/userController.js
================================================
const User = require("../models/User");
const passwordHash = require("password-hash");
const jwt = require("jsonwebtoken");
const ExpressError = require("../config/ExpressError");
const Tool = require("../models/Tool");
require("dotenv").config();
const newUser = async (req, res) => {
try {
const { name, username, password } = req.body;
if (!password || typeof password !== 'string' || password.trim().length === 0)
{
return res.status(400).json({ error: 'Invalid password' });
}
const hashedPassword = passwordHash.generate(password);
const newData = new User({
name: name,
username: username,
password: hashedPassword,
});
await newData.save();
let token = jwt.sign(
{
username: username,
},
process.env.JWT_PASS
);
res.send(token);
} catch (err) {
console.log(err);
return res
.status(500)
.json({ success: false, errors: ["Internal Server Error"] });
}
};
const signIn = async (req, res) => {
try {
const { username, password } = req.body;
const findUser = await User.findOne({ username: username });
if (findUser != null) {
let storedPassword = findUser.password;
if (passwordHash.verify(password, storedPassword)) {
let token = jwt.sign(
{
username: username,
},
process.env.JWT_PASS
);
res.send(token);
} else {
throw new ExpressError(403, "Wrong Password!");
}
} else {
throw new ExpressError(404, "Username not found!");
}
} catch (err) {
console.log(err);
return res
.status(500)
.json({ success: false, errors: ["Internal Server Error"] });
}
};
const addBookmark = async (req, res) => {
try {
const { username, id } = req.body; //id of tool which is being bookmarked
let findUser = await User.findOne({ username: username });
if (findUser != null) {
let findTool = await Tool.findById(id);
if (findTool != null) {
findUser.bookmarks.push(findTool);
await findUser.save();
res.send("Bookmark added!");
} else {
throw new ExpressError(404, "Tool not found!");
}
} else {
throw new ExpressError(404, "User not found!");
}
} catch (err) {
console.log(err);
return res
.status(500)
.json({ success: false, errors: ["Internal Server Error"] });
}
};
module.exports = { newUser, signIn, addBookmark };
================================================
FILE: backend/src/models/OpenSource.js
================================================
const mongoose = require("mongoose");
const OpenSourceSchema = new mongoose.Schema({
projectName: {
type: String,
required: true,
},
ownerUsername: {
type: String,
required: true,
},
tags: {
type: [String],
required: true
},
link: {
type: String,
required: true,
unique: true
},
description: {
type: String,
required: true
}
});
module.exports = mongoose.model("openSource", OpenSourceSchema);
================================================
FILE: backend/src/models/Tool.js
================================================
const mongoose = require("mongoose");
const ToolSchema = new mongoose.Schema({
productName: {
type: String,
required: true
},
category: {
type: String,
enum: ['remote', 'resume', 'tweet', 'ai', 'ethical', 'movies', 'extensions', 'tools','coding', 'productivity','collaboration'],
required: true
},
image: {
type: String,
required: true
},
link: {
type: String,
required: true,
unique: true
},
description: {
type: String,
required: true
}
});
module.exports = mongoose.model("Tool", ToolSchema);
================================================
FILE: backend/src/models/User.js
================================================
const mongoose = require("mongoose");
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
username: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
bookmarks:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"Tool"
}
]
});
const User = mongoose.model("User",userSchema)
module.exports = User
================================================
FILE: backend/src/models/reviewForm.js
================================================
const mongoose = require("mongoose");
const reviewFormSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
msg: {
type: String,
required: true
}
});
module.exports = mongoose.model("reviewForm", reviewFormSchema);
================================================
FILE: backend/src/routes/openSource.js
================================================
const express = require("express");
const router = express.Router();
const openSourceController = require("../controllers/openSourceController");
router.post("/add", openSourceController.addProject);
router.get("/all", openSourceController.fetchAllProjects);
module.exports = router;
================================================
FILE: backend/src/routes/special.js
================================================
const express = require("express");
const router = express.Router();
require("dotenv").config();
const specialController = require("../controllers/specialController");
router.post("/mail", specialController.sendMail);
module.exports = router;
================================================
FILE: backend/src/routes/tools.js
================================================
const express = require("express");
const router = express.Router();
const toolController = require("../controllers/toolController");
router.post("/add", toolController.addTool);
router.get("/all", toolController.fetchAllTools);
module.exports = router;
================================================
FILE: backend/src/routes/user.js
================================================
const express = require("express");
const {
newUser,
signIn,
addBookmark,
} = require("../controllers/userController");
const router = express.Router();
router.post("/signup", newUser);
router.post("/signin", signIn);
router.post("/new/bookmark", addBookmark);
router.use((err, req, res, next) => {
let { status = 500, message = "Some error occured..!" } = err;
res.status(status).send(message);
});
module.exports = router;
================================================
FILE: backend/vercel.json
================================================
{
"version": 2,
"builds": [
{
"src": "server.js",
"use": "@vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "server.js"
}
],
"public": true
}
================================================
FILE: docker-compose.yaml
================================================
version: '3.8'
services:
devlab-frontend:
build:
context: ./frontend
ports:
- "3000:3000"
env_file:
- ./frontend/.env
devlab-backend:
build:
context: ./backend
ports:
- "8000:8000"
env_file:
- ./backend/.env
depends_on:
- mongo
mongo:
image: mongo:latest
ports:
- "27017:27017"
volumes:
- mongo-data:/data/db
volumes:
mongo-data:
================================================
FILE: frontend/.dockerignore
================================================
node_modules
build
.DS_Store
.env
.git
.gitignore
================================================
FILE: frontend/.gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
.github
.vscode
npm-debug.log*
yarn-debug.log*
yarn-error.log*
================================================
FILE: frontend/Dockerfile
================================================
# Build stage
FROM node:alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
RUN npm run build
# Production stage
FROM node:alpine
WORKDIR /app
COPY --from=builder /app/build /app/build
COPY --from=builder /app/package.json /app/package-lock.json /app/
RUN npm install --only=production
EXPOSE 3000
CMD ["npx", "serve", "-s", "build"]
================================================
FILE: frontend/package.json
================================================
{
"name": "myapp",
"version": "0.1.0",
"private": true,
"dependencies": {
"@babel/plugin-transform-class-properties": "^7.21.0",
"@babel/plugin-transform-nullish-coalescing-operator": "^7.21.0",
"@babel/plugin-transform-numeric-separator": "^7.21.0",
"@babel/plugin-transform-optional-chaining": "^7.21.0",
"@babel/plugin-transform-private-methods": "^7.21.0",
"@emotion/react": "^11.13.0",
"@emotion/styled": "^11.13.0",
"@fortawesome/free-brands-svg-icons": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"@fortawesome/react-fontawesome": "^0.2.2",
"@mui/material": "^5.16.4",
"@mui/styled-engine-sc": "^6.0.0-alpha.18",
"@reduxjs/toolkit": "^2.2.6",
"@rollup/plugin-terser": "^0.4.4",
"@testing-library/jest-dom": "^6.4.6",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"antd": "^5.19.3",
"aos": "^2.3.4",
"axios": "^1.7.2",
"bootstrap": "^5.3.3",
"cheerio": "^1.0.0-rc.12",
"darkmode-js": "^1.5.7",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"lottie-react": "^2.4.0",
"mongodb": "^6.8.0",
"pagination": "^0.4.6",
"react": "^18.3.1",
"react-accessible-accordion": "^5.0.0",
"react-chatbot-kit": "^2.2.2",
"react-dom": "^18.3.1",
"react-hot-toast": "^2.4.1",
"react-icons": "^5.2.1",
"react-loading-skeleton": "^3.4.0",
"react-paginate": "^8.2.0",
"react-parallax-tilt": "^1.7.232",
"react-redux": "^9.1.2",
"react-router-dom": "^6.25.1",
"react-scripts": "^5.0.1",
"react-spinners": "^0.14.1",
"react-toastify": "^10.0.5",
"run": "^1.5.0",
"styled-components": "^6.1.12",
"web-vitals": "^4.2.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"resolutions": {
"jest": "28.0.0"
}
}
================================================
FILE: frontend/public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Devlabs is an application that is used to search for free tools that are both free and helpful for our needs. It is built by the amazing open-source community."
/>
<meta
name="keywords"
content="Devlabs, devlabsstore, Developer tools, DevLabs, Free tools, Technology tools, Productivity tools, Daily utilities tools, developer needs, DevLabs, Developer tools"
/>
<meta name="author" content="Himanshu Narware" />
<!-- Open Graph Meta Tags -->
<meta property="og:title" content="Devlabs - Your Free Tool Repository" />
<meta
property="og:description"
content="Search for free and helpful tools tailored to your needs, built by an amazing open-source community."
/>
<meta property="og:image" content="%PUBLIC_URL%/og-image.png" />
<meta property="og:url" content="https://devlabsstore.com" />
<meta property="og:type" content="website" />
<!-- Twitter Card Meta Tags -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Devlabs - Your Free Tool Repository" />
<meta
name="twitter:description"
content="Search for free and helpful tools tailored to your needs, built by an amazing open-source community."
/>
<meta name="twitter:image" content="%PUBLIC_URL%/twitter-image.png" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Dancing+Script:wght@400..700&family=Indie+Flower&family=Jersey+15&family=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="%PUBLIC_URL%/styles.css" />
<!-- Custom CSS for additional styling -->
<script
async
src="https://www.googletagmanager.com/gtag/js?id=G-6WS166VH7E"
></script>
<script
src="https://kit.fontawesome.com/8e211f0d34.js"
crossorigin="anonymous"
></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "G-6WS166VH7E");
</script>
<script src="https://cdn.jsdelivr.net/npm/darkmode-js@1.5.7/lib/darkmode-js.min.js"></script>
<script>
const options = {
bottom: "64px", // default: '32px'
right: "unset", // default: '32px'
left: "32px", // default: 'unset'
time: "0.5s", // default: '0.3s'
mixColor: "#fff", // default: '#fff'
backgroundColor: "#fff", // default: '#fff'
buttonColorDark: "#100f2c", // default: '#100f2c'
buttonColorLight: "#fff", // default: '#fff'
saveInCookies: false, // default: true,
label: "🌓", // default: ''
autoMatchOsTheme: true, // default: true
};
const darkmode = new Darkmode(options);
darkmode.showWidget();
</script>
<title>DEVLABS</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
================================================
FILE: frontend/public/manifest.json
================================================
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "128x128 64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
================================================
FILE: frontend/public/robots.txt
================================================
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
================================================
FILE: frontend/src/App.css
================================================
.sidebar-content {
padding: 10px;
cursor: pointer;
transition: background-color 0.2s;
}
/* cursor: pointer;
transition: background-color 0.2s;
}
}}}} */
================================================
FILE: frontend/src/App.js
================================================
import React, { useState, useEffect, lazy, Suspense } from "react";
import { Route, Routes } from "react-router-dom";
import "./App.css";
import AOS from "aos";
import "aos/dist/aos.css";
import { Toaster } from "react-hot-toast";
// Normal imports for components always needed
import Navbar from "./Component/Navbar/Navbar";
import Footer from "./Component/Footer";
import BackToTopButton from "./Component/BackToTopButton";
import ScrollToTop from "./Component/ScrollToTop";
import ChatAssistant from "./ChatAssistant/ChatAssistant";
// Lazy load components for pages and rarely changed components
const About = lazy(() => import("./Component/About"));
const Rateus = lazy(() => import("./Component/Rateus"));
const Home = lazy(() => import("./Component/Home"));
const NotFound = lazy(() => import("./Component/NotFound"));
const OpenSource = lazy(() => import("./Component/OpenSource"));
const Review = lazy(() => import("./Component/Review"));
const BookMark = lazy(() => import("./Component/BookMark"));
const Contact = lazy(() => import("./Component/Contact"));
const Signup = lazy(() => import("./Component/Signup"));
const Profile = lazy(() => import("./Component/Profile"));
const RemoteJobs = lazy(() => import("./pages/RemoteJobs"));
const AI = lazy(() => import("./pages/AI"));
const UI = lazy(() => import("./pages/UI"));
const Movie = lazy(() => import("./pages/Movie"));
const Extension = lazy(() => import("./pages/Extension"));
const EthicalHacking = lazy(() => import("./pages/EthicalHacking"));
const FrontendTools = lazy(() => import("./pages/FrontendTools"));
const Faq = lazy(() => import("./Component/Faq"));
const CodingPlatform = lazy(() => import("./pages/CodingPlatform"));
const CoursesPlatform = lazy(() => import("./pages/CoursesPlatform"));
const Collaboration = lazy(() => import("./pages/Collaboration"));
const Productivity = lazy(() => import("./pages/Productivity"));
const Extensions = lazy(() => import("./pages/Extensions"));
const Movies = lazy(() => import("./pages/Movies"));
const Ui = lazy(() => import("./pages/UserInterface"));
const RemoteJob = lazy(() => import("./pages/RemoteJob"));
function App() {
const [searchQuery, setSearchQuery] = useState("");
useEffect(() => {
AOS.init();
}, []);
return (
<>
<ScrollToTop />
<Navbar setSearchQuery={setSearchQuery} />
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home searchQuery={searchQuery} />} />
<Route path="/bookmark" element={<BookMark />} />
<Route path="/about" element={<About />} />
<Route path="/open-source" element={<OpenSource />} />
<Route path="/review" element={<Review />} />
<Route path="/faq" element={<Faq />} />
<Route path="/rateus" element={<Rateus />} />
<Route path="/remote-jobs" element={<RemoteJobs />} />
<Route path="/ai" element={<AI />} />
<Route path="/movies-series" element={<Movie />} />
<Route path="/extension" element={<Extension />} />
<Route path="/ui-design" element={<UI />} />
<Route path="/front-end-tools" element={<FrontendTools />} />
<Route path="/ethical-hacking" element={<EthicalHacking />} />
<Route path="/coding-platform" element={<CodingPlatform />} />
<Route path="/courses-platform" element={<CoursesPlatform />} />
<Route path="*" element={<NotFound />} /> {/* 404 route */}
</Routes>
</Suspense>
<BackToTopButton />
<Footer />
<ChatAssistant />
<Toaster />
</>
);
}
export default App;
================================================
FILE: frontend/src/ChatAssistant/Avatar.jsx
================================================
import chatbotLogo from "../assets/chatbotLogo.jpeg"
import React from 'react'
import "../ChatAssistant/ChatAssistant.css"
export default function Avatar() {
return (
<div>
<img
className="Avatar"
src={chatbotLogo}
alt="chatbot_avatar"
/>
</div>
)
}
================================================
FILE: frontend/src/ChatAssistant/ChatAssistant.css
================================================
.chatbot {
position: fixed;
bottom: 70px;
right: 70px;
margin-right: 20px;
margin-bottom: 12px;
/* z-index: 999; */
/* cursor:none; */
}
.chatbot-close-animation {
animation: animate-close ease-in 0.3s forwards;
}
.chatbot-animation {
animation: animate ease-in 0.3s forwards;
}
@keyframes animate {
from {
height: 0px;
/* width: 250px; */
}
to {
height: 450px;
width: 350px;
}
}
@keyframes animate-close {
from {
height: 450px;
width: 350px;
}
to {
height: 0px;
width: 0px;
}
}
.react-chatbot-kit-chat-input {
outline: none;
}
.react-chatbot-kit-chat-inner-container {
background-color: #0f6874;
}
.react-chatbot-kit-chat-container {
width: 350px;
height: 450px;
}
.react-chatbot-kit-chat-bot-message {
margin-left: 10px;
}
.react-chatbot-kit-chat-header {
background-color: rgb(153, 189, 230);
}
.react-chatbot-kit-chat-bot-message {
background-color: #000000;
}
.react-chatbot-kit-chat-bot-message-arrow {
border-right: 8px solid #000000;
}
.react-chatbot-kit-chat-input-form{
width: 90%;
margin: auto;
border: none;
}
.react-chatbot-kit-chat-input{
background-color: #000000;
color: aliceblue;
border-radius: 10px 0px 0px 10px;
}
.react-chatbot-kit-chat-btn-send {
background-color: #8b5cf6;
border-radius: 0px 10px 10px 0px;
height: 45px;
}
.react-chatbot-kit-chat-btn-send-icon{
fill: #070707;
width: 24px;
height: auto;
}
.react-chatbot-kit-user-chat-message{
background: #8b5cf6;
color: #000000;
width: 100px;
height: 50px;
align-content: center;
font-size: 16px;
font-weight: 500;
}
.react-chatbot-kit-user-chat-message-container{
gap: 5px;
}
.react-chatbot-kit-user-chat-message-arrow{
border-left: 8px solid #8b5cf6;
}
.react-chatbot-kit-chat-message-container{
overflow-y: scroll;
overflow-x: hidden;
max-height: 350px;
}
.react-chatbot-kit-chat-inner-container{
border-radius: 30px;
}
.react-chatbot-kit-chat-container{
margin-top: -30px;
}
.chatbot-header p{
color: #000000;
font-size: 20px;
font-weight: 600;
}
.hidden{
display: none;
}
.react-chatbot-kit-chat-message-container::-webkit-scrollbar {
width: 6px;
}
.react-chatbot-kit-chat-message-container::-webkit-scrollbar-track {
background: #888;
}
.react-chatbot-kit-chat-message-container::-webkit-scrollbar-thumb {
background: #8b5cf6;
border-radius: 10px;
}
.react-chatbot-kit-chat-message-container::-webkit-scrollbar-thumb:hover {
background: #aa86fd;
}
.Logo {
height: 50px;
width: 50px;
/* cursor: none; */
height:50px;
width:50px;
}
/* height: 50px;
width: 50px; */
.Logo {
height: 50px;
width: 50px;
border-radius: 50px;
right: 12px;
}
.Avatar {
height: 50px;
width: 50px;
border-radius: 50px;
}
.userAvatar {
height: 50px;
width: 50px;
border-radius: 50px;
}
.close-button {
background-color: #8b5cf6;
height: 35px;
width: 35px;
border-radius: 50px;
color: black;
font-size: 20px;
/* cursor: none; */
position: absolute;
z-index: 5;
margin-left: 130px;
margin-top: 7px;
}
.close-button:hover{
background-color: #0f6874;
color: #ffff;
}
@media only screen and (max-width: 425px) {
.chatbot {
margin-right: 5px;
margin-bottom: 5px;
}
.react-chatbot-kit-chat-container {
width: 300px;
height: 400px;
padding-bottom: 30px;
}
.react-chatbot-kit-chat-message-container {
height: 350px;
}
.Avatar {
height: 36px;
width: 36px;
border-radius: 50px;
}
.userAvatar {
height: 36px;
width: 36px;
border-radius: 50px;
}
}
.chatbot:hover .tooltiptext{
top: -2.5em;
left: -1em;
visibility: visible;
opacity: 1;
}
.tooltiptext{
position: absolute;
top: 0;
left: 2em;
transform: transLateX(-50%);
background-color:rgb(224, 192, 247);
color: rgb(129, 2, 157);
white-space: nowrap;
padding: 5px 10px;
border-radius: 7px;
visibility: hidden;
transition: opacity 0.5s ease;
}
================================================
FILE: frontend/src/ChatAssistant/ChatAssistant.jsx
================================================
import React, { useState } from "react";
import Chatbot from "react-chatbot-kit";
import "react-chatbot-kit/build/main.css";
import config from "../ChatBot/config";
import MessageParser from "../ChatBot/MessageParser";
import ActionProvider from "../ChatBot/ActionProvider";
import "./ChatAssistant.css";
import chatbotLogo from "../assets/chatbotLogo.jpeg";
import chatbotLogo1 from "../assets/logo1.png";
const ChatAssistant = () => {
const [isOpen, setIsOpen] = useState(false);
const toggleChatbot = () => {
setIsOpen(!isOpen);
};
const closeChatbot = () => {
setIsOpen(false);
};
return (
<div className='chatbot'>
<span className={`tooltiptext ${isOpen ? 'hidden' : ''}`}>Chat bot</span>
<img
className={`Logo ${isOpen ? 'hidden' : ''}`}
src={chatbotLogo}
alt='Logo'
onClick={toggleChatbot}
onMouseEnter={() => (document.querySelector(".Logo").src = chatbotLogo1)}
onMouseLeave={() => (document.querySelector(".Logo").src = chatbotLogo)}
/>
{isOpen && (
<div className={`chatbot-wrapper ${isOpen ? 'chatbot-animation' : 'chatbot-close-animation'}`}>
<button className='close-button' onClick={closeChatbot}>
X
</button>
<Chatbot
config={config}
messageParser={MessageParser}
actionProvider={ActionProvider}
/>
</div>
)}
</div>
);
};
export default ChatAssistant;
================================================
FILE: frontend/src/ChatAssistant/UserAvatar.jsx
================================================
import userAvatar from "../assets/userAvatar.jpg"
import React from 'react'
import "../ChatAssistant/ChatAssistant.css"
export default function Avatar() {
return (
<div>
<img
className="userAvatar"
src={userAvatar}
alt="useravatar_pic"
/>
</div>
)
}
================================================
FILE: frontend/src/ChatBot/ActionProvider.jsx
================================================
import React from 'react';
import { createChatBotMessage } from 'react-chatbot-kit';
const ActionProvider = ({ setState, children }) => {
const updateState = (message) => {
setState((prev) => ({
...prev,
messages: [...prev.messages, message],
}));
};
const handleEmptyMessage = () => {
const message = createChatBotMessage("I'm waiting for your message...");
updateState(message);
};
const handleHello = () => {
const message = createChatBotMessage('Hello, I am DevLabs ChatBot. Type your query..');
updateState(message);
};
const websiteDetails = () => {
const message = createChatBotMessage('DevLabs is a website where you can search for free tools that are useful for your daily needs. This application is created by the incredible open-source community. For further details, visit our About Us section.');
updateState(message);
};
const contactUs = () => {
const message = createChatBotMessage('Contact details can be viewed in our Contact section, which is available in the footer section. Feel free to contact us.');
updateState(message);
};
const contribute = () => {
const message = createChatBotMessage('Contribution details can be viewed in our Open Source section, which is available in the footer section. Feel free to contribute to our project.');
updateState(message);
};
const greeting = () => {
const message = createChatBotMessage('Happy to help you. Visit again to our website. Thank you!');
updateState(message);
};
return (
<div>
{React.Children.map(children, (child) => {
return React.cloneElement(child, {
actions: {
handleHello,
websiteDetails,
contactUs,
contribute,
greeting,
handleEmptyMessage,
},
});
})}
</div>
);
};
export default ActionProvider;
================================================
FILE: frontend/src/ChatBot/MessageParser.jsx
================================================
import React from "react";
const MessageParser = ({ children, actions }) => {
const parse = (message) => {
if(!message || message.trim() === ""){
actions.handleEmptyMessage();
return;
}
if (
message.includes("hello") ||
message.includes("hi") ||
message.includes("hey") ||
message.includes("Hi")
) {
actions.handleHello();
} else if (
message.includes("Tell me about your website") ||
message.includes("about website") ||
message.includes("About website") ||
message.includes("Your website") ||
message.includes("your website") ||
message.includes("Mission of website") ||
message.includes("mission of website") ||
message.includes("what does this website do?") ||
message.includes("What does this website do?") ||
message.includes("What is DevLabs?") ||
message.includes("What is Devlabs?") ||
message.includes("what is devlabs?") ||
message.includes("What is DevLabs?") ||
message.includes("What is Devlabs?") ||
message.includes("what is devlabs?")
) {
actions.websiteDetails();
} else if (
message.includes("how to contact") ||
message.includes("How to contact") ||
message.includes("How to contact?")
) {
actions.contactUs();
} else if (
message.includes("how to contribute") ||
message.includes("How to contribute") ||
message.includes("How to contribute?") ||
message.includes("How do i contribute in this project?")
) {
actions.contribute();
} else if (
message.includes("thanks") ||
message.includes("thank you") ||
message.includes("thanks a lot") ||
message.includes("thanks for help") ||
message.includes("Thanks") ||
message.includes("Thank You")
) {
actions.greeting();
}
};
return (
<div>
{React.Children.map(children, (child) => {
return React.cloneElement(child, {
parse: parse,
actions,
});
})}
</div>
);
};
export default MessageParser;
================================================
FILE: frontend/src/ChatBot/config.jsx
================================================
import { createChatBotMessage } from 'react-chatbot-kit';
import Avatar from "../ChatAssistant/Avatar";
import UserAvatar from "../ChatAssistant/UserAvatar"
import "../ChatAssistant/ChatAssistant.css";
const config = {
botName: "DevLabs ChatBot",
initialMessages: [createChatBotMessage(`Welcome to DevLabs! Explore our Website 🙌`)],
customComponents:{
botAvatar: (props) => <Avatar {...props} />,
userAvatar: (props) => <UserAvatar {...props} />,
header: () => <div className="chatbot-header" style={{ backgroundColor: '#8b5cf6',
padding: "12px",
borderRadius: "15px 15px 5px 5px",
textAlign:"center" ,
fontWeight: '20px',
height:"50px",
display:"flex" }}>
<p>DevLabs ChatBot</p>
</div>
},
}
export default config;
================================================
FILE: frontend/src/Component/About.js
================================================
import React, { useState, useEffect } from "react";
import "../style/About.css";
import Pagination from "./Pagination";
import { getPaginationData, changePage } from "../utils/paginationData";
const FOUNDER = "HimanshuNarware";
const LINKEDIN_URL = "https://www.linkedin.com/in/HimanshuNarware";
const CARDS_PER_PAGE = 12;
function About() {
const [contributors, setContributors] = useState([]);
const [founder, setFounder] = useState({});
const [currentPage, setCurrentPage] = useState(1);
const [searchQuery, setSearchQuery] = useState("");
const repoOwner = "HimanshuNarware";
const repoName = "Devlabs";
useEffect(() => {
async function fetchContributors() {
try {
const response = await fetch(
`https://api.github.com/repos/${repoOwner}/${repoName}/contributors`
);
if (!response.ok) {
throw new Error(
`GitHub API request failed with status ${response.status}`
);
}
const data = await response.json();
const contributorsList = data.filter(
(contributor) => contributor.login !== FOUNDER
);
const founderObj = data.find(
(contributor) => contributor.login === FOUNDER
);
setContributors(contributorsList);
setFounder(founderObj);
} catch (error) {
console.error("Error fetching contributors:", error);
}
}
fetchContributors();
}, []);
const filteredContributors = contributors.filter((contributor) =>
contributor.login.toLowerCase().includes(searchQuery.toLowerCase())
);
const paginationValues = getPaginationData(
currentPage,
CARDS_PER_PAGE,
filteredContributors
);
const { lastCardIndex, firstCardIndex, allPagesNumbers, currentPageData } =
paginationValues;
const handlePageChange = (value) => {
changePage(value, currentPage, setCurrentPage, allPagesNumbers);
};
const filledData = [...currentPageData];
const placeholdersNeeded = CARDS_PER_PAGE - filledData.length;
for (let i = 0; i < placeholdersNeeded; i++) {
filledData.push({ placeholder: true, id: `placeholder-${i}` });
}
return (
<div>
<div className="about__container-one">
<div className="about__box about__box--1" data-aos="">
<p>
Devlabs is an application used to search for tools that are both
free and helpful for our needs. It is built by the amazing
open-source community.
</p>
<button className="about__repo-btn">
<a
href="https://github.com/HimanshuNarware/Devlabs"
target="_blank"
rel="noreferrer"
>
Star the repo ★
</a>
</button>
</div>
<div className="about__box about__box--2 aos-init" data-aos="flip-left">
<img
className="about__img"
src="https://img.freepik.com/free-vector/illustrated-woman-being-intern-company_23-2148726151.jpg?size=626&ext=jpg"
alt="img"
/>
</div>
</div>
<div className="about__container-two">
<div className="about__box about__box--2">
<img
className="about__img"
src="https://img.freepik.com/free-vector/developer-activity-concept-illustration_114360-1554.jpg?t=st=1726407511~exp=1726411111~hmac=f2dbc71c1557c1284496c3bb3d243d58894cd840fad5b42c528679d5fb57d2c4&w=740"
alt="img"
/>
</div>
<div className="about__box about__box--1">
<p>
Great things are never created in isolation. Thanks to our amazing
contributors, we've brought this product to life. With your help, we
can continue to make it even better. If you're a developer or a Tech
enthusiast, you can help us create a better experience for
everyone. We are excited to hear your thoughts and ideas.
</p>
<button className="about__repo-btn">
<a
href="https://github.com/HimanshuNarware"
target="_blank"
rel="noreferrer"
>
Learn more ➜
</a>
</button>
</div>
</div>
<div className="about__contributor-container">
<h1>Founder</h1>
<div className="about__founder-container">
<div className="about__content-box">
<img
className="about__profile-img"
src={founder.avatar_url}
alt="profile"
/>
<h3 className="about__founder-username">{founder.login}</h3>
<div className="about__buttons-container">
<button className="about__profile-btn">
<a href={founder.html_url} target="_blank" rel="noreferrer">
GitHub
</a>
</button>
<button className="about__profile-btn">
<a href={LINKEDIN_URL} target="_blank" rel="noreferrer">
Linkedin
</a>
</button>
</div>
</div>
</div>
<h1 id="contributors">Our Contributors</h1>
<input
type="text"
className="about__searchbar-contributors"
placeholder="Search your name here..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
<div className="about__grid-container">
{filledData.map((contributor) => {
if (contributor.placeholder) {
return (
<div
className="about__content-box about__content-box-placeholder"
key={contributor.id}
></div>
);
}
return (
<div className="about__content-box" key={contributor.id}>
<img
className="about__logo"
src={contributor.avatar_url}
alt="avatar"
/>
<h3>{contributor.login}</h3>
<h4>{contributor.contributions} commits</h4>
<button className="about__profile-btn">
<a
href={contributor.html_url}
target="_blank"
rel="noreferrer"
>
Profile
</a>
</button>
</div>
);
})}
</div>
</div>
<Pagination
firstCardIndex={firstCardIndex}
lastCardIndex={lastCardIndex}
dataLength={filteredContributors.length}
allPagesNumbers={allPagesNumbers}
currentPage={currentPage}
scrollPosition={"contributors"}
handlePageChange={handlePageChange}
/>
</div>
);
}
export default About;
================================================
FILE: frontend/src/Component/BackToTopButton.js
================================================
import React, { useState, useEffect } from 'react';
import '../style/BackToTopButton.css';
import { MdKeyboardDoubleArrowUp } from "react-icons/md";
function BackToTopButton() {
const [isVisible, setIsVisible] = useState(false);
const [scrollProgress, setScrollProgress] = useState(0);
useEffect(() => {
const handleScroll = () => {
try {
const documentHeight = document.documentElement.scrollHeight - window.innerHeight;
const scrollOffset = documentHeight * 0.5;
const scrollTop = window.scrollY;
const progress = (scrollTop / documentHeight) * 100;
setIsVisible(scrollTop > scrollOffset);
setScrollProgress(progress);
} catch (error) {
console.error("Scroll handling error: ", error);
}
};
const debounceHandleScroll = debounce(handleScroll, 100);
window.addEventListener('scroll', debounceHandleScroll);
return () => {
window.removeEventListener('scroll', debounceHandleScroll);
};
}, []);
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: 'smooth',
});
};
const iconStyle = {
width: '2.5rem',
height: '2.5rem',
filter: 'brightness(0) invert(1)',
};
return (
<button
onClick={scrollToTop}
className={`back-to-top-button ${isVisible ? 'visible' : ''}`}
aria-label="Back to top"
>
<MdKeyboardDoubleArrowUp style={iconStyle} />
<div className="scroll-progress">
<svg className="progress-ring" width="60" height="60">
<circle
className="progress-ring__circle"
stroke="#0658ea"
strokeWidth="6"
fill="transparent"
r="26"
cx="30"
cy="30"
style={{ strokeDasharray: 163.362, strokeDashoffset: 163.362 - (163.362 * scrollProgress) / 100 }}
/>
</svg>
</div>
<span className='tooltiptext'>Go top page</span>
</button>
);
}
function debounce(func, wait) {
let timeout;
return function (...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
export default BackToTopButton;
================================================
FILE: frontend/src/Component/BookMark.js
================================================
import React, { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { deleteSource } from "../Slice/DataSlice";
import bookmarkAnimation from "../lottie/bookmark.json";
import "../style/BookMark.css";
import Lottie from "lottie-react";
import toast from "react-hot-toast";
function BookMark() {
const sourceData = useSelector((state) => state.SourceReducer.sourceData); // Adjust the selector to match your state structure
const dispatch = useDispatch();
const [currentPage, setCurrentPage] = useState(1);
const [postPerPage] = useState(8); // Number of bookmarks per page
useEffect(() => {
localStorage.setItem("bookmarks", JSON.stringify(sourceData));
}, [sourceData]);
const handleDeleteBookmark = (name) => {
console.log("remove", name);
dispatch(deleteSource({ name }));
toast.success("Bookmark removed successfully");
};
// Get current bookmarks
const indexOfLastPost = currentPage * postPerPage;
const indexOfFirstPost = indexOfLastPost - postPerPage;
const currentBookmarks = sourceData.slice(indexOfFirstPost, indexOfLastPost);
// Change page
const paginate = (pageNumber) => setCurrentPage(pageNumber);
const nextPage = () => setCurrentPage(currentPage + 1);
const prevPage = () => setCurrentPage(currentPage - 1);
return (
<div className="bookmark">
<div className="bookmark__container">
{currentBookmarks?.length > 0 ? (
currentBookmarks?.map((data, index) => (
<div className="bookmark__box" key={index}>
<img
className="bookmark__logo"
src={data.image}
alt={data.name}
/>
<h2>{data.name}</h2>
<p className="bookmark__box-text">{data.desc}</p>
<button
className="bookmark__button"
onClick={() => window.open(data.link)}
>
Link
</button>
<button
className="bookmark__button"
onClick={() => handleDeleteBookmark(data.name)}
>
Remove
</button>
</div>
))
) : (
<div></div>
)}
</div>
<div>
{/* Pagination */}
{sourceData.length > postPerPage && currentBookmarks.length > 0 && (
<ul className="pagination">
{currentPage !== 1 && (
<li className="page-item">
<button onClick={prevPage} className="page-link">
Prev
</button>
</li>
)}
{Array.from({
length: Math.ceil(sourceData.length / postPerPage),
}).map((_, index) => (
<li
key={index}
className={`page-item ${
currentPage === index + 1 ? "active" : ""
}`}
>
<button
onClick={() => paginate(index + 1)}
className="page-link"
>
{index + 1}
</button>
</li>
))}
{currentPage !== Math.ceil(sourceData.length / postPerPage) && (
<li className="page-item">
<button onClick={nextPage} className="page-link">
Next
</button>
</li>
)}
</ul>
)}
</div>
{sourceData.length === 0 && (
<div>
<Lottie
animationData={bookmarkAnimation}
style={{ height: "200px" }}
/>
<h1 className="text-2xl font-semibold">No bookmark Found</h1>
<h3 className="mb-4">
Explore Devlabs and add them to your bookmark
</h3>
</div>
)}
</div>
);
}
export default BookMark;
================================================
FILE: frontend/src/Component/Contact.jsx
================================================
import {
faFacebook,
faGithub,
faLinkedin,
faTwitter,
} from "@fortawesome/free-brands-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Lottie from "lottie-react";
import React, { useState } from "react";
import { Bounce, ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import animationData from "../lottie/contact.json";
import "../style/Contact.css";
const Contact = () => {
const [email, setEmail] = useState("");
const [isValid, setIsValid] = useState(true);
const handleEmailChange = (event) => {
const { value } = event.target;
setEmail(value);
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
setIsValid(emailRegex.test(value));
};
const handleSubmit = (event) => {
event.preventDefault();
if (isValid && email) {
toast("✅ Sent Successfully!", {
position: "top-center",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: false,
draggable: true,
progress: undefined,
theme: "light",
transition: Bounce,
closeButton: true,
});
}
};
return (
<div className="outer-contact">
<div className="contact-container">
<div className="contact-content">
<div className="image-container">
<Lottie
animationData={animationData}
loop={true}
className="lottie-animation"
/>
</div>
<div className="form-container">
<h2 className="contact-heading">Contact Us</h2>
<p className="contact-description">
Please fill out the form below to get in touch with us.
</p>
<form className="contact-form" onSubmit={handleSubmit}>
<div className="form-group">
<label htmlFor="name" className="form-label">
Name
</label>
<input
type="text"
id="name"
name="name"
className="form-input"
placeholder="Full name"
/>
</div>
<div className="form-group">
<label htmlFor="email" className="form-label">
Email
</label>
<input
type="email"
id="email"
name="email"
className={`form-input ${isValid ? "" : "invalid"}`}
onChange={handleEmailChange}
placeholder="example@example.com"
/>
{!isValid && (
<p className="error-message">
Please enter a valid email address.
</p>
)}
</div>
<div className="form-group">
<label htmlFor="message" className="form-label">
Message
</label>
<textarea
id="message"
name="message"
className="form-textarea"
rows="4"
placeholder="Write your message..."
></textarea>
</div>
<button type="submit" className="submit-button">
Submit
</button>
</form>
<div className="social-links">
<a
href="https://www.linkedin.com/in/himanshunarware/"
target="_blank"
rel="noopener noreferrer"
className="social-link"
>
<FontAwesomeIcon icon={faLinkedin} className="social-icon" />
</a>
<a
href="https://github.com/HimanshuNarware/Devlabs"
target="_blank"
rel="noopener noreferrer"
className="social-link"
>
<FontAwesomeIcon icon={faGithub} className="social-icon" />
</a>
<a
href="https://twitter.com/"
target="_blank"
rel="noopener noreferrer"
className="social-link"
>
<FontAwesomeIcon icon={faTwitter} className="social-icon" />
</a>
<a
href="https://facebook.com/"
target="_blank"
rel="noopener noreferrer"
className="social-link"
>
<FontAwesomeIcon icon={faFacebook} className="social-icon" />
</a>
</div>
</div>
</div>
</div>
<ToastContainer
position="top-center"
autoClose={5000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover={false}
theme="light"
transition={Bounce}
/>
</div>
);
};
export default Contact;
================================================
FILE: frontend/src/Component/Faq.js
================================================
import React, { useState } from "react";
import "../style/faq.css";
import {
Accordion,
AccordionItem,
AccordionItemHeading,
AccordionItemButton,
AccordionItemPanel,
AccordionItemState,
} from "react-accessible-accordion";
import { MdOutlineArrowDropDown } from "react-icons/md";
import data from "./accordion";
import "react-accessible-accordion/dist/fancy-example.css";
export default function Faq() {
let [index, setIndex] = useState(0);
const [setClassName] = useState(null);
return (
<section className="faq">
<div className="faq__content">
<div className="faq__header">
<span className="faq__header-text">Frequently Asked Questions</span>
<Accordion
className="faq__border-none faq__mt-8"
allowMultipleExpanded={false}
preExpanded={[0]}
>
{data.map((item, i) => {
return (
<AccordionItem
className={`faq__border-2 faq__border-gray faq__rounded-lg faq__overflow-hidden faq__mb-5 ${
index === i ? "faq__accordion-open" : "faq__accordion-close"
}`}
key={i}
uuid={i}
>
<AccordionItemHeading>
<AccordionItemButton className="faq__accordion-item">
{/* <AccordionItemState>
{({ expanded }) =>
expanded
? setClassName("expanded")
: setClassName("collapsed")
}
</AccordionItemState> */}
<div
className="faq__accordion-button"
onClick={() => setIndex(i)}
>
<div className="faq__accordion-icon">{item.icon}</div>
<span className="font-bold">{item.heading}</span>
<MdOutlineArrowDropDown
style={{ color: "white" }}
size={20}
/>
</div>
</AccordionItemButton>
</AccordionItemHeading>
<AccordionItemPanel>
<p className="faq__accordion-detail">
<p className="custom-text1">{item.detail}</p>
</p>
</AccordionItemPanel>
</AccordionItem>
);
})}
</Accordion>
</div>
</div>
</section>
);
}
================================================
FILE: frontend/src/Component/Footer.js
================================================
import React from "react";
import logo from "../image/logo1.png";
import "../style/Footer.css";
import {
FaGithubSquare,
FaLinkedinIn,
FaFacebookF,
FaHome,
FaBookmark,
FaQuestionCircle,
FaRegHeart,
FaBriefcase,
FaRobot,
FaFilm,
FaTools,
FaLaptopCode,
FaUser,
FaLock,
} from "react-icons/fa";
import {
AiOutlineInstagram,
AiOutlineTwitter,
AiOutlineMail,
AiFillStar,
} from "react-icons/ai";
import { BsYoutube, BsFillPersonLinesFill, BsCodeSlash } from "react-icons/bs";
import { Link } from "react-router-dom";
function Footer() {
return (
<footer>
<div className="Footer">
<div className="container">
<div className="row">
<div className="col-md-6 col-lg-4 col-12 ft-1">
<a href="https://www.devlabsstore.tech/">
<img width={209} src={logo} alt="devlabs" />
</a>
<p className="footer-content">
Welcome to DevLabs, a website where you can search for free
tools that are useful for your daily needs. This application is
created by the incredible open-source community. On DevLabs, you
can discover a collection of free tools that can assist you in
various aspects of your life.
</p>
<h3>Facing an issue or just enjoying the site?</h3>
<button>
<Link to="/review">Tell us Now</Link>
</button>
</div>
<div className="col-md-6 col-lg-2 col-12 ft-2 ft-space">
<h3>Company</h3>
<ul>
<li className="nav-item">
<a href="https://www.devlabsstore.tech/">
<FaHome className="mr-2" /> Home
</a>
</li>
<li className="nav-item">
<a href="https://www.devlabsstore.tech/about">
<FaQuestionCircle className="mr-2" /> About Us
</a>
</li>
<li className="nav-item">
<a href="https://www.devlabsstore.tech/bookmark">
<FaBookmark className="mr-2" /> Bookmark
</a>
</li>
<li className="nav-item">
<a href="https://www.linkedin.com/in/himanshunarware/">
<BsFillPersonLinesFill className="mr-2" /> Contact
</a>
</li>
<li className="nav-item">
<a href="https://www.devlabsstore.tech/rateus">
<AiFillStar className="mr-2" /> Rate Us
</a>
</li>
<li className="nav-item">
<a href="https://www.devlabsstore.tech/profile">
<FaUser className="mr-2" /> My Profile
</a>
</li>
<li className="nav-item">
<a href="https://www.devlabsstore.tech/open-source">
<FaRegHeart className="mr-2" /> Open Source
</a>
</li>
<li className="nav-item">
<a href="https://github.com/HimanshuNarware/Devlabs">
<FaGithubSquare className="mr-2" /> Contribute Here
</a>
</li>
</ul>
</div>
<div className="col-md-6 col-lg-2 col-12 ft-2 ft-space">
<h3>Quick Links</h3>
<ul>
<li className="nav-item">
<a href="/remote-job">
<FaBriefcase className="mr-2" /> Remote Jobs
</a>
</li>
<li className="nav-item">
<a href="/ai">
<FaRobot className="mr-2" /> AI
</a>
</li>
<li className="nav-item">
<a href="/movies&series">
<FaFilm className="mr-2" /> Movie/Series
</a>
</li>
<li className="nav-item">
<a href="/extensions">
<FaTools className="mr-2" /> Extension
</a>
</li>
<li className="nav-item">
<a href="/ui-designs">
<FaLaptopCode className="mr-2" /> UI Design
</a>
</li>
</ul>
</div>
<div className="col-md-6 col-lg-2 col-12 ft-2 ft-last">
<h3>Explore</h3>
<ul>
<li className="nav-item">
<a href="/front-end-tools">
<FaTools className="mr-2" /> Frontend Tools
</a>
</li>
<li className="nav-item">
<a href="/ethical-hacking">
<FaLock className="mr-2" /> Ethical Hacking
</a>
</li>
<li className="nav-item">
<a href="/coding-platform">
<BsCodeSlash className="mr-2" /> Coding Platforms
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div className="Last-footer">
<div className="container">
<div className="row justify-content-center">
<div className="col-md-6 col-12 ft-1">
<div className="text-center fs-6 my-3">
COPYRIGHT © Devlabs 2024 | <br /> MAINTAINED BY HIMANSHU NARWARE
</div>
<div className="text-center mb-2">
<a
href="https://github.com/sponsors/HimanshuNarware"
target="_blank"
rel="noopener noreferrer"
>
<img
src="https://badgen.net/badge/icon/github?icon=github&label=Sponsor&color=orange"
alt="Sponsor Me on GitHub"
style={{ height: "30px", width: "auto" }}
/>
</a>
</div>
<div className="outerD gap-4 md:gap-2">
<span className="icons">
<a href="/" target="_blank" rel="noopener noreferrer">
<AiOutlineInstagram
color="white"
fontSize={25}
className="ico"
/>
</a>
</span>
<span className="icons">
<a href="/" target="_blank" rel="noopener noreferrer">
<AiOutlineTwitter
color="white"
fontSize={25}
className="ico"
/>
</a>
</span>
<span className="icons">
<a href="/" target="_blank" rel="noopener noreferrer">
<BsYoutube color="white" fontSize={25} className="ico" />
</a>
</span>
<span className="icons">
<a href="/" target="_blank" rel="noopener noreferrer">
<FaLinkedinIn color="white" fontSize={25} className="ico" />
</a>
</span>
<span className="icons">
<a href="/" target="_blank" rel="noopener noreferrer">
<FaFacebookF color="white" fontSize={25} className="ico" />
</a>
</span>
<span className="icons">
<a href="/" target="_blank" rel="noopener noreferrer">
<FaGithubSquare
color="white"
fontSize={25}
className="ico"
/>
</a>
</span>
<span className="icons">
<a
href="mailto:example@gmail.com"
target="_blank"
rel="noopener noreferrer"
>
<AiOutlineMail
color="white"
fontSize={25}
className="ico"
/>
</a>
</span>
</div>
<hr />
</div>
</div>
</div>
</div>
</footer>
);
}
export default Footer;
================================================
FILE: frontend/src/Component/Home.js
================================================
import axios from "axios";
import React, { useEffect, useState, useRef } from "react";
import { useDispatch } from "react-redux";
import ClipLoader from "react-spinners/ClipLoader";
import jsonTools from "../DB/product.json";
import { deleteSource, setSource } from "../Slice/DataSlice";
import "../style/Home.css";
import Devlabs from "../image/hero_img.svg";
import NavbarItem from "./Navbar/NavbarItem";
import toast from "react-hot-toast";
const BACKEND = process.env.REACT_APP_BACKEND;
function Home(props) {
const [bookmarks, setBookmark] = useState(null);
const [localStorageValue, setLocalStorageValue] = useState(
localStorage.getItem("filter") || ""
);
const ref = useRef();
if (props.searchQuery !== "") {
ref.current?.scrollIntoView({
behavior: "smooth",
});
}
const [currentPage, setCurrentPage] = useState(1);
const postPerpage = 44;
const lastPostIndex = currentPage * postPerpage;
const firstPostIndex = lastPostIndex - postPerpage;
const [dataBaseData, setDataBaseData] = useState([]);
const [loading, setLoading] = useState(false);
const currentPost1 = dataBaseData;
let allvalue = [];
function handleBookmarks() {
const bookmark = JSON.parse(localStorage.getItem("bookmarks"));
setBookmark(bookmark);
}
useEffect(() => {
handleBookmarks();
}, []);
useEffect(() => {
setLoading(true);
const handleStorageChange = () => {
setLocalStorageValue(localStorage.getItem("filter"));
};
window.addEventListener("storage", handleStorageChange);
const fetchData = async () => {
const response = await axios
.get(`${BACKEND}/tools/all`)
.catch((error) => {
return error.response;
});
if (response.data.success) {
setDataBaseData(response.data.tools);
} else {
setDataBaseData(jsonTools);
}
setLoading(false);
};
fetchData();
return () => {
window.removeEventListener("storage", handleStorageChange);
};
}, []);
if (localStorageValue === "undefined" || localStorageValue === "all") {
allvalue = dataBaseData;
} else if (localStorageValue !== "all" && localStorageValue !== "undefined") {
if (localStorage.getItem("filter-2")) {
allvalue = currentPost1.filter(
(e) =>
e.category.toLowerCase().includes(localStorageValue) ||
e.category.includes(localStorage.getItem("filter-2"))
);
} else {
allvalue = currentPost1.filter((e) =>
e.category.toLowerCase().includes(localStorageValue)
);
}
}
const filteredData = !!props.searchQuery
? allvalue.filter((datalist) => {
return datalist.productName
.toLowerCase()
.includes(props.searchQuery.toLowerCase());
})
: allvalue;
const currentPost =
filteredData.length > 16
? filteredData.slice(firstPostIndex, lastPostIndex)
: filteredData;
const npage = Math.ceil(filteredData.length / postPerpage);
const numbers = [...Array(npage + 1).keys()].slice(1);
const dispatch = useDispatch();
function prePage() {
if (currentPage > 1) {
setCurrentPage(currentPage - 1);
}
}
function nextPage() {
if (currentPage < npage) {
setCurrentPage(currentPage + 1);
}
}
function changeCPage(id) {
setCurrentPage(id);
}
function handleBookmark(datalist) {
if (bookmarks === null) {
localStorage.setItem(
"bookmarks",
JSON.stringify([
{
image: datalist.image,
name: datalist.productName,
desc: datalist.description,
link: datalist.link,
},
])
);
dispatch(
setSource({
image: datalist.image,
name: datalist.productName,
desc: datalist.description,
link: datalist.link,
})
);
toast.success("Bookmark added successfully");
} else {
let found = false;
for (let item of bookmarks) {
if (item.name === datalist.productName) {
found = true;
break;
}
}
if (!found) {
localStorage.setItem(
"bookmarks",
JSON.stringify([
...bookmarks,
{
image: datalist.image,
name: datalist.productName,
desc: datalist.description,
link: datalist.link,
},
])
);
toast.success("Bookmark added successfully");
dispatch(
setSource({
image: datalist.image,
name: datalist.productName,
desc: datalist.description,
link: datalist.link,
})
);
}
}
handleBookmarks();
}
const handleDeleteBookmark = (name) => {
dispatch(deleteSource({ name }));
toast.success("Bookmark removed successfully");
const bookmarksInStorage =
JSON.parse(localStorage.getItem("bookmarks")) || [];
const updatedBookmarks = bookmarksInStorage.filter(
(bookmark) => bookmark.name !== name
);
localStorage.setItem("bookmarks", JSON.stringify(updatedBookmarks));
handleBookmarks();
};
return (
<div>
<div className="hero">
<div className="hero-text">
<div id="hero" className="hero-container">
<div className="hero-content">
<h1 className="hero-heading">
<span>Welcome to</span>
<br /> Devlabs!
<h1 className="hero-subheading">
Discover Free Tools,
<br />
Empower Your Projects.
<br />
<span className="hero-end">
{" "}
-Built by open-source community
</span>
</h1>
</h1>
<div className="hero-button-container">
<button className="hero-button">
<NavbarItem description="Get Started" to="/open-source" />
</button>
</div>
</div>
<div className="hero-image">
<img src={Devlabs} alt="devlabs-removebg-preview" />
</div>
</div>
</div>
</div>
<div ref={ref} className="page-container">
<div className={loading ? "loading-container" : "main-container"}>
<ClipLoader
color="#808080"
loading={loading}
size={50}
aria-label="Loading Spinner"
data-testid="loader"
/>
{currentPost.map((datalist) => {
return (
<div className="content-box-home" key={datalist.productName}>
<img
className="logo"
src={datalist.image}
alt={datalist.category}
/>
<h2>{datalist.productName}</h2>
<p className="content-box-text">{datalist.description}</p>
<button
className="btn-b-box"
onClick={() => window.open(datalist.link)}
>
Link
</button>
{bookmarks?.some((item) =>
item.name.includes(datalist.productName)
) ? (
<>
<button
className="btn-booked-box"
onClick={() => handleDeleteBookmark(datalist.productName)}
>
Remove
</button>
</>
) : (
<button
className="btn-b-box"
onClick={() => handleBookmark(datalist)}
>
Bookmark
</button>
)}
</div>
);
})}
</div>
<div className="pagination">
<ul>
<li>
<a href="#!" onClick={prePage}>
<
</a>
</li>
{numbers.map((n, i) => (
<li key={i} className={`${currentPage === n ? "active" : ""}`}>
<a href="#!" onClick={() => changeCPage(n)}>
{n}
</a>
</li>
))}
<li>
<a href="#!" onClick={nextPage}>
>
</a>
</li>
</ul>
</div>
</div>
</div>
);
}
export default Home;
================================================
FILE: frontend/src/Component/Login.css
================================================
/* src/Component/Login.css */
.login-container {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
max-width: 400px;
margin: auto;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
background-color: #fff;
}
h2 {
font-size: 24px;
margin-bottom: 20px;
}
form {
display: flex;
flex-direction: column;
width: 100%;
}
input {
padding: 10px;
margin-bottom: 15px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
}
button {
padding: 10px;
font-size: 16px;
color: #fff;
background-color: #007bff;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
================================================
FILE: frontend/src/Component/Login.js
================================================
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import './Login.css'; // Add your own styles
const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate();
const handleLogin = async (e) => {
e.preventDefault();
// Add your authentication logic here
// For example, send a request to your backend
console.log('Login:', { email, password });
// On success, navigate to the home page or user profile
navigate('/');
};
return (
<div className="login-container">
<h2>Login</h2>
<form onSubmit={handleLogin}>
<input
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button type="submit">Login</button>
</form>
</div>
);
};
export default Login;
================================================
FILE: frontend/src/Component/Modal.js
================================================
// Modal.jsx
import React from 'react';
import "./../style/Modal.css";
function Modal({ isOpen, onClose, children }) {
if (!isOpen) {
return null;
}
return (
<div className="modal-overlay">
<div className="modal-content">
<button className="close-buttoned" onClick={onClose}>
×
</button>
{children}
</div>
</div>
);
}
export default Modal;
================================================
FILE: frontend/src/Component/Navbar/Navbar.js
================================================
import React, { useState } from "react";
import "../../style/Navbar.css";
import Sidebar from "../Sidebar/Sidebar";
import NavbarLeft from "./NavbarLeft";
import NavbarCenter from "./NavbarCenter";
function Navbar(props) {
const [showSideNav, setShowSideNav] = useState(false);
return (
<header>
<div className="navbar">
<NavbarLeft showSideNav={showSideNav} setShowSideNav={setShowSideNav} />
<div style={{ marginLeft: "auto" }}>
<NavbarCenter showSideNav={showSideNav} />
</div>
{/* Pass setSearchQuery directly
<NavbarRight setSearchQuery={props.setSearchQuery} />
*/}
</div>
<Sidebar showSideNav={showSideNav} />
</header>
);
}
export default Navbar;
================================================
FILE: frontend/src/Component/Navbar/NavbarCenter.js
================================================
import React, { useState } from "react";
import { useSelector } from "react-redux";
import "../../style/Navbar.css";
import NavbarItem from "./NavbarItem";
import Modal from "../../Component/Modal";
import RateUsComponent from "../../Component/Rateus"; // Import the RateUsComponent
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faHome, faBookmark, faCode, faInfoCircle, faQuestionCircle, faStar, faEnvelope } from '@fortawesome/free-solid-svg-icons';
function NavbarCenter() {
const totalBookmarks = useSelector((state) => state.SourceReducer.totalBookmarks) || 0;
const [isModalOpen, setIsModalOpen] = useState(false);
const handleRateUsClick = () => {
setIsModalOpen(true);
};
return (
<nav className="navbar-center">
<ul className="navbar-content mb-2">
<li className="nav-item">
<NavbarItem description={<><FontAwesomeIcon icon={faHome} /> Home</>} to="/" />
</li>
<li className="nav-item">
<NavbarItem description={<><FontAwesomeIcon icon={faBookmark} /> Bookmark ({totalBookmarks})</>} to="/bookmark" />
</li>
<li className="nav-item">
<NavbarItem description={<><FontAwesomeIcon icon={faCode} /> Open Source</>} to="/open-source" />
</li>
<li className="nav-item">
<NavbarItem description={<><FontAwesomeIcon icon={faInfoCircle} /> About Us</>} to="/about" />
</li>
{/* <li className="nav-item">
<NavbarItem description={<><FontAwesomeIcon icon={faQuestionCircle} /> FAQ's</>} to="/faq" />
</li> */}
<li className="nav-item" onClick={handleRateUsClick}>
<NavbarItem description={<><FontAwesomeIcon icon={faStar} /> Rate Us</>} to="#" />
</li>
<li className="nav-item">
<NavbarItem description={<><FontAwesomeIcon icon={faEnvelope} /> Contact</>} to="https://www.linkedin.com/in/himanshunarware/" />
</li>
</ul>
<Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)}>
<RateUsComponent />
</Modal>
</nav>
);
}
export default NavbarCenter;
================================================
FILE: frontend/src/Component/Navbar/NavbarItem.js
================================================
import React from "react";
import { Link } from "react-router-dom";
function NavbarItem({ description, to }) {
return (
<Link to={to} className="Link nav-link active" aria-current="page">
{description}
</Link>
);
}
//done
export default NavbarItem;
================================================
FILE: frontend/src/Component/Navbar/NavbarLeft.js
================================================
import React, { useEffect } from "react";
import "../../style/Navbar.css"
import logo from "../../image/logo1.png";
function NavbarLeft(props, showSideNav) {
useEffect(() => {
const handleDocumentClick = (e) => {
if (!e.target.closest('.navbar-left')) {
props.setShowSideNav(false);
}
};
document.body.addEventListener('click', handleDocumentClick);
return () => {
// Removed event listener on component unmount
document.body.removeEventListener('click', handleDocumentClick);
};
}, [props]);
function handleClick(e) {
e.preventDefault();
props.setShowSideNav(!props.showSideNav);
}
function handleItemClick() {
props.setShowSideNav(false);
}
return (
<span className="navbar-left" style={{marginTop : showSideNav ? "0px":"0px"}}>
<a
onClick={handleClick}
className="navbar-brand sdbar-logo"
href="/"
id="logo"
>
<div className={props.showSideNav?"open":""} id="nav-icon1">
<span></span>
<span></span>
<span></span>
</div>
</a>
<a href="/" onClick={handleItemClick}> {/* Added onClick handler */}
<img className="navbar-brand logo-img" src={logo} alt="this" />
</a>
</span>
);
}
export default NavbarLeft;
================================================
FILE: frontend/src/Component/Navbar/NavbarRight.js
================================================
import React, { useEffect, useState } from "react";
import { BsSearch } from "react-icons/bs";
import { RxCross2 } from "react-icons/rx";
import "../../style/Navbar.css";
function NavbarRight({ setSearchQuery }) {
const [searchQuery, setLocalSearchQuery] = useState(""); // Local state to manage search query
//debounce search query
useEffect(() => {
let timer = setTimeout(() => {
setSearchQuery(searchQuery);
}, 300);
return () => {
clearTimeout(timer);
};
}, [searchQuery, setSearchQuery]);
const handleInputChange = (e) => {
setLocalSearchQuery(e.target.value); // Update the search query when input changes
};
const handleSearch = (e) => {
e.preventDefault();
setSearchQuery(searchQuery); // Pass the search query to the parent component (App)
};
const clearSearchHandler = (e) => {
e.preventDefault();
setLocalSearchQuery("");
setSearchQuery(""); // Pass the empty search query to the parent component (App)
};
return (
<div className="navbar-right" id="navbarTogglerDemo03">
<div className="search">
<form role="search" className="search-bar" onSubmit={handleSearch}>
<div className="box" focus>
<input
type="text"
className="input"
placeholder="Search . . ."
value={searchQuery} // Set input value to the search query
onChange={handleInputChange}
/>
<button
className={`span ${!searchQuery && "invisible"}`}
type="button"
onClick={clearSearchHandler}
>
<RxCross2 />
</button>
<button className="span" type="submit">
<BsSearch />
</button>
</div>
</form>
</div>
</div>
);
}
export default NavbarRight;
================================================
FILE: frontend/src/Component/Navbar/Progress.js
================================================
import React from 'react'
import "../../style/Navbar.css"
const Progress = () => {
window.onscroll = function () {
var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var scrolled = (winScroll / height) * 100;
document.getElementById("progressBar").style.width = scrolled + "%";
};
return (
<div id="progressBar"></div>
)
}
export default Progress
================================================
FILE: frontend/src/Component/NotFound.js
================================================
import React from "react";
import { Link } from "react-router-dom";
import "../style/NotFound.css";
function NotFound() {
return (
<div className="not-found-container">
<div className="not-found-content">
<h1 className="not-found-heading">404 - Page Not Found</h1>
<p className="not-found-text">
The page you are looking for does not exist. It may have been moved or deleted.
</p>
<Link to="/" className="not-found-button">
Go back to the Home page
</Link>
<img
src="https://internetdevels.com/sites/default/files/public/blog_preview/404_page_cover.jpg"
alt="404 Error"
className="not-found-image"
/>
</div>
</div>
);
}
export default NotFound;
================================================
FILE: frontend/src/Component/OpenSource.js
================================================
import React, { useState, useEffect } from "react";
import "../style/OpenSource.css";
import ReactPaginate from "react-paginate";
import axios from "axios";
import ClipLoader from "react-spinners/ClipLoader";
import jsonProjects from "../DB/openSource.json";
const BACKEND = process.env.REACT_APP_BACKEND;
const OpenSource = () => {
const projectsPerPage = 16;
const [projects, setProjects] = useState([]);
const [currentPage, setCurrentPage] = useState(0);
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
const fetchData = async () => {
const response = await axios
.get(`${BACKEND}/open-source/all`)
.catch((error) => {
return error.response;
});
if (response.data && response.data.success) {
setProjects(response.data.openSourceProjects);
} else {
setProjects(jsonProjects);
}
setLoading(false);
};
fetchData();
}, []);
const handlePageClick = (event) => {
setCurrentPage(event.selected);
};
const offset = currentPage * projectsPerPage;
const currentPageProjects = projects.slice(
offset,
offset + projectsPerPage
);
const totalPages = Math.ceil(projects.length / projectsPerPage);
return (
<div className="open-source__page-container">
<div className={loading ? "open-source__loading-container" : "open-source__main-container"}>
<ClipLoader
color="#a0a0a0"
loading={loading}
size={50}
aria-label="Loading Spinner"
data-testid="loader"
/>
{currentPageProjects.map((project) => (
<div className="open-source__content-box-home" key={project.projectName}>
<h2>{project.projectName}</h2>
<p className="open-source__content-box-subtitle">
- By {project.ownerUsername}
</p>
<p className="open-source__content-box-text">
{project.description}
</p>
<button
className="open-source__btn-b-box"
onClick={() => {
window.open(project.link);
}}
>
Project
</button>
<div className="open-source__tag-grid">
{project.tags &&
project.tags.map((tag) => (
<span className="open-source__tag" key={tag}>
{tag}
</span>
))}
</div>
</div>
))}
</div>
{totalPages > 1 && (
<ReactPaginate
breakLabel="..."
nextLabel={currentPage < totalPages - 1 ? "next >" : null}
onPageChange={handlePageClick}
pageRangeDisplayed={4}
pageCount={totalPages}
previousLabel={currentPage > 0 ? "< prev" : null}
renderOnZeroPageCount={null}
containerClassName="open-source__pagination"
pageClassName="open-source__page-item"
pageLinkClassName="open-source__page-link"
previousClassName={`open-source__page-item ${
currentPage === 0 ? "open-source__disabled" : ""
}`}
previousLinkClassName="open-source__page-link"
nextClassName={`open-source__page-item ${
currentPage === totalPages - 1 ? "open-source__disabled" : ""
}`}
nextLinkClassName="open-source__page-link"
activeClassName="open-source__active"
/>
)}
</div>
);
};
export default OpenSource;
================================================
FILE: frontend/src/Component/Pagination.js
================================================
import React from 'react'
import "../style/Pagination.css"
const Pagination = ({
firstCardIndex,
lastCardIndex,
dataLength,
allPagesNumbers,
currentPage,
handlePageChange,
scrollPosition
}) => {
return (
<nav>
<div className="page-index">
Showing {firstCardIndex + 1}-{lastCardIndex} from {dataLength} results
</div>
<ul className="pagination_about_us">
{(currentPage > 1) &&
<li className="page-item">
<a href={`#${scrollPosition}`} className="page-link" onClick={() => handlePageChange("prev")}>
prev
</a>
</li>
}
{allPagesNumbers.map((pageNum, i) => (
<li
className={`page-item ${currentPage === pageNum ? "active" : ""}`}
key={`li-${i}`}
>
<a href={`#${scrollPosition}`} className="page-link" onClick={() => handlePageChange(pageNum)}>
{pageNum}
</a>
</li>
))}
{(currentPage < allPagesNumbers[allPagesNumbers.length - 1]) &&
<li className="page-item">
<a href={`#${scrollPosition}`} className="page-link" onClick={() => handlePageChange("next")}>
next
</a>
</li>
}
</ul>
</nav>
)
}
export default Pagination
================================================
FILE: frontend/src/Component/Preloader.js
================================================
import React ,{useState,useEffect} from 'react';
import '../style/preloader.css';
import pre from '../lottie/pre.json'
import Lottie from 'lottie-react';
import App from '../App';
function Preloader() {
const [loading,setLoading]=useState(false);
useEffect(()=>{
setLoading(true);
setTimeout(() =>{
setLoading(false)
},2000)
},[])
return (
loading ?
<div className='pre'>
<Lottie className="preloader" animationData={pre}/>
</div>
:
//Rest Code
<App/>
);
}
export default Preloader;
================================================
FILE: frontend/src/Component/PrivacyPolicy.css
================================================
/* PrivacyPolicy.css */
.privacy-policy-container {
padding: 20px;
max-width: 800px;
margin: 0 auto;
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
}
.privacy-policy-container h1 {
font-size: 2.5em;
margin-top: 85px;
margin-bottom: 20px;
color: #000000;
}
.privacy-policy-container h2 {
font-size: 1.8em;
margin-top: 30px;
color: #0056b3;
}
.privacy-policy-container p {
margin-bottom: 15px;
}
.privacy-policy-container ul {
list-style-type: disc;
padding-left: 20px;
}
.privacy-policy-container ul li {
margin-bottom: 10px;
}
.privacy-policy-container a {
color: #007bff;
text-decoration: none;
}
.privacy-policy-container a:hover {
text-decoration: underline;
}
.Footer {
padding: 3rem 0;
margin-top: -1rem;
background: #6a43c3;
color: white;
}
================================================
FILE: frontend/src/Component/PrivacyPolicy.js
================================================
import React from 'react';
import './PrivacyPolicy.css';
const PrivacyPolicy = () => {
return (
<div className="privacy-policy-container">
<h1>Privacy Policy</h1>
<p>Welcome to DevLabs, a website where you can search for free tools that are useful for your daily needs. This application is created by the incredible open-source community. On DevLabs, you can discover a collection of free tools that can assist you in various aspects of your life. Moreover, you have the opportunity to contribute to this project by adding more tools to the database.</p>
<h2>Information We Collect</h2>
<p>We collect information that you provide to us directly when you use our website, such as when you create an account, add tools, or communicate with us. This information may include your name, email address, and any other details you choose to provide.</p>
<h2>How We Use Your Information</h2>
<p>We use the information we collect to provide, maintain, and improve our services, including to personalize your experience on DevLabs, provide customer support, and communicate with you about updates and news.</p>
<h2>Sharing of Information</h2>
<p>We do not share your personal information with third parties without your consent, except in the following circumstances:</p>
<ul>
<li>With service providers who perform services on our behalf.</li>
<li>To comply with laws or to respond to lawful requests and legal process.</li>
<li>To protect the rights and property of DevLabs and our users.</li>
</ul>
<h2>Security</h2>
<p>We take reasonable measures to protect your personal information from loss, theft, misuse, and unauthorized access, disclosure, alteration, and destruction.</p>
<h2>Changes to This Privacy Policy</h2>
<p>We may update our Privacy Policy from time to time. We will notify you of any changes by posting the new Privacy Policy on this page. You are advised to review this Privacy Policy periodically for any changes.</p>
<h2>Contact Us</h2>
<p>If you have any questions about this Privacy Policy, please contact us at <a href="mailto:support@devlabs.com">support@devlabs.com</a>.</p>
</div>
);
};
export default PrivacyPolicy;
================================================
FILE: frontend/src/Component/Profile.js
================================================
import React, { useEffect, useState } from "react";
import "../style/Profile.css";
function Profile() {
const [profileData, setProfileData] = useState({
name: "",
bio: "",
email: "",
github: "",
website: ""
});
const [isSubmitted, setIsSubmitted] = useState(false);
const [image, setImage] = useState(null);
const [preview, setPreview] = useState(null);
// Le data from localStorage when the component mounts
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [showLogin, setShowLogin] = useState(true); // Toggle between login and signup
const [formData, setFormData] = useState({
email: "",
password: "",
name: ""
});
const [error, setError] = useState("");
const [passwordError, setPasswordError] = useState("");
useEffect(() => {
const savedData = localStorage.getItem("profileData");
if (savedData) {
setProfileData(JSON.parse(savedData));
setIsSubmitted(true);
}
const isLoggedIn = localStorage.getItem("isLoggedIn");
if (isLoggedIn) {
setIsLoggedIn(true);
}
}, []);
const handleChange = (e) => {
const { name, value } = e.target;
setProfileData((prevData) => ({
...prevData,
[name]: value
}));
};
const handleImageChange = (e) => {
const file = e.target.files[0];
setImage(file);
setPreview(URL.createObjectURL(file));
};
const handleProfileSubmit = (e) => {
e.preventDefault();
localStorage.setItem("profileData", JSON.stringify(profileData));
setIsSubmitted(true);
};
const handleAuthChange = (e) => {
const { name, value } = e.target;
setFormData(prevData => ({
...prevData,
[name]: value
}));
};
const handleAuthSubmit = (e) => {
e.preventDefault();
if (formData.email && formData.password) {
if (validatePassword(formData.password)) {
localStorage.setItem("isLoggedIn", "true");
setIsLoggedIn(true);
setError(""); // Clear any previous errors
} else {
setPasswordError("Password must be a valid hexadecimal string with at least 6 characters.");
}
} else {
setError("Please fill out all fields.");
}
};
const handleLogout = () => {
localStorage.removeItem("isLoggedIn");
setIsLoggedIn(false);
setIsSubmitted(false);
};
const handleAuthSwitch = () => {
setShowLogin(prev => !prev);
setError("");
};
const [password, setPassword] = useState("");
const validatePassword = (password) => {
const Pattern = /^[0-9a-fA-F]+$/;
return Pattern.test(password) && password.length >= 6;
}
if (!isLoggedIn) {
return showLogin ? (
<div className="auth__container">
<h1>LOGIN</h1>
<form className="auth__form" onSubmit={handleAuthSubmit}>
<div className="auth__form-group">
<label htmlFor="email">Email:</label>
<input
type="email"
id="email"
name="email"
placeholder="youremail@mail.com"
value={formData.email}
onChange={handleAuthChange}
required
/>
</div>
<div className="auth__form-group">
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
name="password"
value={formData.password}
onChange={handleAuthChange}
required
/>
{passwordError && <p className="auth__error">{passwordError}</p>}
</div>
{error && <p className="auth__error">{error}</p>}
<button type="submit" className="auth__submit-btn">Login</button>
<p className="auth__switch-container">
Don't have an account? <button className="signup-btn-switch" onClick={handleAuthSwitch}>Signup</button>
</p>
</form>
</div>
) : (
<div className="auth__container">
<h1>Sign Up</h1>
<form className="auth__form" onSubmit={handleAuthSubmit}>
<div className="auth__form-group">
<label htmlFor="name">Name:</label>
<input
type="text"
id="name"
name="name"
placeholder="Your Name"
value={formData.name}
onChange={handleAuthChange}
required
/>
</div>
<div className="auth__form-group">
<label htmlFor="email">Email:</label>
<input
type="email"
id="email"
name="email"
placeholder="youremail@mail.com"
value={formData.email}
onChange={handleAuthChange}
required
/>
</div>
<div className="auth__form-group">
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
name="password"
value={formData.password}
onChange={handleAuthChange}
required
/>
</div>
{passwordError && <p className="auth__error">{passwordError}</p>}
{error && <p className="auth__error">{error}</p>}
<div className="signup__form-group">
<label>
<input
type="checkbox"
name="subscribe"
checked={formData.subscribe}
onChange={handleChange}
/>
Subscribe to promotions and newsletter
</label>
</div>
<button type="submit" className="auth__submit-btn">Sign Up</button>
<p className="auth__terms">By creating this account, you agree to our <a>terms & conditions</a>.</p>
<p className="auth__switch-container">
Already have an account? <button className="login-btn-switch" onClick={handleAuthSwitch}>Login</button>
</p>
</form>
</div>
);
}
return isSubmitted ? (
<div className="profile__container">
<div className="profile__row">
<div>
<div className="profile__avatar">
<div className="profile__avatar-placeholder">
{preview ? (
<img src={preview} alt="Profile" className="profile__avatar-img" />
) : (
<div className="profile__avatar-placeholder">
{profileData.name.charAt(0).toUpperCase()}
</div>
)}
</div>
</div>
<h2 className="profile__name">{profileData.name}</h2>
</div>
<div className="profile__right">
<div className="profile__details">
<p className="profile__bio">{profileData.bio}</p>
<div className="profile__info">
<p><span><i class="fa-solid fa-envelope"></i> </span><strong>Email:</strong> {profileData.email}</p>
{profileData.github && (
<p><span><i class="fa-brands fa-github-alt"></i> </span><strong>GitHub:</strong> <a href={profileData.github} target="_blank" rel="noreferrer">{profileData.github}</a></p>
)}
{profileData.website && (
<p><span><i class="fa-solid fa-link"></i> </span><strong>Website:</strong> <a href={profileData.website} target="_blank" rel="noreferrer">{profileData.website}</a></p>
)}
</div>
</div>
<div className="profile__buttons">
<button className="profile__edit-btn" onClick={() => setIsSubmitted(false)}>Edit Profile</button>
<button className="profile__logout-btn" onClick={handleLogout}>Logout</button>
</div>
</div>
</div>
</div>
) : (
<div className="profile__container">
<h1>Edit Profile</h1>
<form className="profile__form" onSubmit={handleProfileSubmit}>
<div className="profile__form-group">
<label htmlFor="name">Name:</label><br />
<input
type="text"
id="name"
name="name"
value={profileData.name}
onChange={handleChange}
required
placeholder="Enter your name"
/>
</div>
<div className="profile__form-group">
<label htmlFor="bio">Bio:</label><br />
<textarea
id="bio"
name="bio"
value={profileData.bio}
onChange={handleChange}
rows="3"
placeholder="Enter your bio"
></textarea>
</div>
<div className="profile__form-group">
<label htmlFor="email">Email:</label><br />
<input
type="email"
id="email"
name="email"
value={profileData.email}
onChange={handleChange}
required
placeholder="youremail@mail.com"
/>
</div>
<div className="profile__form-group">
<label htmlFor="github">GitHub URL:</label><br />
<input
type="url"
id="github"
name="github"
value={profileData.github}
onChange={handleChange}
placeholder="Enter your github url"
/>
</div>
<div className="profile__form-group">
<label htmlFor="website">Website:</label><br />
<input
type="url"
id="website"
name="website"
value={profileData.website}
onChange={handleChange}
placeholder="Enter your personal website url"
/>
</div>
<div className="profile__form-group">
<label htmlFor="profileImage">Profile Image:</label>
<br />
<input
type="file"
id="profileImage"
name="profileImage"
onChange={handleImageChange}
accept="image/*"
/>
</div>
<button type="submit" className="profile__submit-btn">Save Profile</button>
</form>
</div>
);
}
export default Profile;
================================================
FILE: frontend/src/Component/Rate.css
================================================
input[type=radio]{
display: none;
}
.Rate .star{
cursor: pointer;
}
.star FaStar{
border: 1px solid #fff;
}
================================================
FILE: frontend/src/Component/Rate.jsx
================================================
import React, { useState } from 'react'
import { FaStar } from 'react-icons/fa'
import "./Rate.css"
const Rate = () => {
const [rating, setRating] = useState(null);
const [hover, setHover] = useState(null);
return (
<div className='Rate'>
{[...Array(5)].map((star, index) => {
const currentRating = index +1;
return(
<label>
<input type="radio" name='rating' value={currentRating} onClick={() => setRating(currentRating)}/>
<FaStar
className='star'
size={50}
color={currentRating <= (hover || rating) ? "#0739ff":"#e4e5e9"}
onMouseEnter={() => setHover(currentRating)}
onMouseLeave={() => setHover(null)}
/>
</label>
);
})}
<p>Your Rating is {rating} out of 5. </p>
</div>
)
}
export default Rate
================================================
FILE: frontend/src/Component/Rateus.js
================================================
import React, { useState } from "react";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import "./../style/Rateus.css";
function RateUsComponent({ previousContent }) {
const [rating, setRating] = useState(0);
const [feedback, setFeedback] = useState("");
const handleFeedbackChange = (e) => {
setFeedback(e.target.value);
};
const handleEmojiClick = (emojiIndex) => {
setRating(emojiIndex);
};
const handleSubmit = () => {
if (rating !== 0 && feedback.trim() !== "") {
setRating(0);
setFeedback("");
toast.success("Thanks For Your Feedback :)", {
position: "top-center"
});
} else {
toast.error("Please Enter All Details :(", {
position: "top-center"
});
}
};
const emojis = ["😢", "😟", "😐", "😊", "😍"];
return (
<>
<div className="rate-us-page">
<div className="rate-us-container">
<h2 className="rate-us-heading">Rate Our Website</h2>
<div className="emoji-rating">
{emojis.map((emoji, index) => (
<span
key={index}
className={index + 1 === rating ? "emoji selected" : "emoji"}
onClick={() => handleEmojiClick(index + 1)}
>
{emoji}
</span>
))}
</div>
<textarea
className="feedback-textarea"
placeholder="Write your feedback here..."
value={feedback}
onChange={handleFeedbackChange}
></textarea>
<button className="submit-button" onClick={handleSubmit}>
Submit
</button>
</div>
</div>
<ToastContainer />
</>
);
}
export default RateUsComponent;
================================================
FILE: frontend/src/Component/Register.css
================================================
/* src/Component/Register.css */
.register-container {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
max-width: 400px;
margin: auto;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
background-color: #fff;
}
h2 {
font-size: 24px;
margin-bottom: 20px;
}
form {
display: flex;
flex-direction: column;
width: 100%;
}
input {
padding: 10px;
margin-bottom: 15px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
}
button {
padding: 10px;
font-size: 16px;
color: #fff;
background-color: #007bff;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
================================================
FILE: frontend/src/Component/Register.js
================================================
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import './Register.css'; // Add your own styles
const Register = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const navigate = useNavigate();
const handleRegister = async (e) => {
e.preventDefault();
if (password !== confirmPassword) {
alert('Passwords do not match');
return;
}
// Add your registration logic here
// For example, send a request to your backend
console.log('Register:', { email, password });
// On success, navigate to the login page or home page
navigate('/login');
};
return (
<div className="register-container">
<h2>Register</h2>
<form onSubmit={handleRegister}>
<input
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<input
type="password"
placeholder="Confirm Password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
/>
<button type="submit">Register</button>
</form>
</div>
);
};
export default Register;
================================================
FILE: frontend/src/Component/Review.js
================================================
import React, { useState } from "react";
import ClipLoader from "react-spinners/ClipLoader";
import "../style/Review.css";
import axios from "axios";
import Rate from "./Rate";
import { toast } from "react-toastify";
const BACKEND = process.env.REACT_APP_BACKEND;
function Review() {
const [rating, setRating] = useState(0);
const [reviewData, setReviewData] = useState({
name: "",
email: "",
review: "",
feedbackType: "",
otherFeedback: ""
});
const [processingMail, setProcessingMail] = useState(false);
const onChangeHandler = (event) => {
setReviewData({ ...reviewData, [event.target.id]: event.target.value });
};
const onFeedbackTypeChange = (event) => {
setReviewData({ ...reviewData, feedbackType: event.target.value, otherFeedback: "" });
};
const onSubmitHandler = async (event) => {
event.preventDefault();
const emailPattern = /^[a-zA-Z0-9._-]+@gmail.com$/;
const email = document.getElementById("email").value;
if (!emailPattern.test(email)) {
toast.error("Please enter a valid email address.");
return;
}
else{
toast.success("Review Submitted");
}
setProcessingMail(true);
const response = await axios
.post(`${BACKEND}/special/mail`, reviewData, {
headers: {
"Content-Type": "application/json",
},
})
.catch((error) => {
return error.response;
});
setProcessingMail(false);
if (response.data.success) toast.success("Mail Sent Successfully!!");
else if (response.data && response.data.errors) {
toast.error(response.data.errors.join("\n"));
} else {
toast.error("An unknown error occurred.");
}
window.location.reload();
};
return (
<div>
<h2 className='review__form-header'>Here's the Review Form</h2>
<div>
<p className='review__form-subtext'>
Thank you for visiting the website! Please tell us how we can improve
your experience. Provide your email in case you want the owner to
contact you.
</p>
</div>
<form className='review__form' onSubmit={onSubmitHandler}>
<input
className='review__form-input review__input-name'
placeholder='Your Name'
type='text'
id='name'
value={reviewData.name}
onChange={onChangeHandler}
required
/>
<input
className='review__form-input review__input-email'
placeholder='Your Email'
type='email'
id='email'
value={reviewData.email}
onChange={onChangeHandler}
required
/>
<div className='review__form-input' style={{ align: 'Left', display: 'flex', flexDirection: 'column', alignItems: 'flex-start' }}>
<label htmlFor='feedbackType' style={{ marginBottom: '10px' }}>Feedback Type:</label>
<select
id='feedbackType'
value={reviewData.feedbackType}
onChange={onFeedbackTypeChange}
style={{ width: '100%' }}
required
>
<option value=''>Select feedback type</option>
<option value='complaint'>Complaint</option>
<option value='suggestion'>Suggestion</option>
<option value='question'>Question</option>
<option value='other'>Other</option>
</select>
</div>
{reviewData.feedbackType === 'other' && (
<input
className='review__form-input'
placeholder='Please specify'
type='text'
id='otherFeedback'
value={reviewData.otherFeedback}
onChange={onChangeHandler}
required
/>
)}
<textarea
className='review__form-input review__input-review'
placeholder='Your Message'
id='review'
cols='30'
rows='5'
value={reviewData.review}
onChange={onChangeHandler}
required
/>
<h3>Rate us:</h3>
<Rate rating={rating} setRating={setRating} />
<div className='review__form-div'>
<button className='review__form-button'>
{processingMail ? (
<ClipLoader
color='#a0a0a0'
loading={processingMail}
size={20}
aria-label='Loading Spinner'
data-testid='loader'
/>
) : (
"Submit"
)}
</button>
</div>
</form>
</div>
);
}
export default Review;
================================================
FILE: frontend/src/Component/ScrollToTop.jsx
================================================
import {useEffect} from 'react'
import { useLocation } from 'react-router-dom'
function ScrollToTop() {
const { pathname } = useLocation();
useEffect(()=>{
window.scrollTo(0,0);
},[pathname])
return null;
}
export default ScrollToTop;
================================================
FILE: frontend/src/Component/Sidebar/Sidebar.js
================================================
import React from "react";
import { Link } from "react-router-dom";
import { BsBookmark } from "react-icons/bs";
import { AiFillHome } from "react-icons/ai";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faHome,
faBookmark,
faCode,
faInfoCircle,
faTasks,
faQuestionCircle,
faStar,
faUser,
faEnvelope,
} from "@fortawesome/free-solid-svg-icons";
import { FaRobot, FaUserSecret, FaFilm, FaCogs, FaLaptopCode, FaTools, FaBook, FaUsers, FaTasks } from "react-icons/fa";
import "../../style/Sidebar.css";
function Sidebar({ showSideNav }) {
const sidebarContent = [
{ name: "all", description: "All", url: "/", icon: AiFillHome },
{ name: "remote", description: "Remote Jobs", url: "/remote-jobs", icon: BsBookmark },
{ name: "ai", description: "AI", url: "/ai", icon: FaRobot },
{ name: "ethical", description: "Ethical Hacking", url: "/ethical-hacking", icon: FaUserSecret },
{ name: "movies", description: "Movie | Series", url: "/movies-series", icon: FaFilm },
{ name: "extension", description: "Extension", url: "/extension", icon: FaCogs },
{ name: "ui", description: "UI Design", url: "/ui-design", icon: FaLaptopCode },
{ name: "frontend-tools", description: "Frontend Tools", url: "/front-end-tools", icon: FaTools },
{ name: "backend-tools", description: "Backend Tools", url: "/back-end-tools", icon: FaTools },
{ name: "coding", description: "Coding Platforms", url: "/coding-platform", icon: FaBook },
{ name: "productivity", description: "Productivity Tools", url: "/productivity-tools", icon: FaTasks },
{ name: "collaboration", description: "Collaboration Tools", url: "/collaboration-tools", icon: FaUsers },
];
return (
<div style={{ marginTop: "10px" }} className={`sidebar ${showSideNav ? "active" : ""}`}>
<div className={`sidebar-content sidebar-btns ${showSideNav ? "active" : ""}`}>
<div className="sidebar-btn home-btn" key="home">
<Link to="/" className="Link Bookmark nav-link active" aria-current="page">
<AiFillHome /> Home
</Link>
</div>
<div className="sidebar-btn bookmark-btn" key="bookmark">
<Link to="/bookmark" className="Link Bookmark nav-link active" aria-current="page">
<BsBookmark /> BookMark
</Link>
</div>
<div className="sidebar-btn home-btn" key="about">
<Link to="/about" className="Link Bookmark nav-link active" aria-current="page">
<FontAwesomeIcon icon={faInfoCircle} /> About Us
</Link>
</div>
<div className="sidebar-btn bookmark-btn" key="contact">
<Link to="/contact" className="Link Bookmark nav-link active" aria-current="page">
<FontAwesomeIcon icon={faEnvelope} /> Contact
</Link>
</div>
<div className="sidebar-btn bookmark-btn" key="open-source">
<Link to="/open-source" className="Link Bookmark nav-link active" aria-current="page">
<FontAwesomeIcon icon={faCode} /> Open Source
</Link>
</div>
<div className="sidebar-btn bookmark-btn" key="faq">
<Link to="/faq" className="Link Bookmark nav-link active" aria-current="page">
<FontAwesomeIcon icon={faQuestionCircle} /> FAQ's
</Link>
</div>
<div className="sidebar-btn bookmark-btn" key="rate-us">
<Link to="/rateus" className="Link Bookmark nav-link active" aria-current="page">
<FontAwesomeIcon icon={faStar} /> Rate Us
</Link>
</div>
<div className="sidebar-btn profile-btn" key="profile">
<Link to="/profile" className="Link Bookmark nav-link active" aria-current="page">
<FontAwesomeIcon icon={faUser} /> My Profile
</Link>
</div>
</div>
{sidebarContent.map((item) => (
<div className="sidebar-btn" key={item.name}>
<Link to={item.url} className="Link Bookmark nav-link active" aria-current="page">
{item.icon ? <item.icon /> : <FontAwesomeIcon icon={faTasks} />} {item.description}
</Link>
</div>
))}
</div>
);
}
export default Sidebar;
================================================
FILE: frontend/src/Component/Sidebar/SidebarContent.js
================================================
import React from "react";
function SidebarContent({name,description,active}) {
function handleSidebarClick(prop) {
localStorage.setItem("filter", prop);
if (prop === "tools") {
localStorage.setItem("filter-2", "web");
}
window.dispatchEvent(new Event("storage"));
}
return (
<div
className={`sidebar-content filter ${active?"active":""}`}
onClick={() => handleSidebarClick(name)}
>
{description}
</div>
);
}
export default SidebarContent;
================================================
FILE: frontend/src/Component/Signup.js
================================================
import React, { useState } from 'react';
import '../style/Signup.css'; // Import CSS file for styling
export default function Signup() {
const [name, setName] = useState('');
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = async (event) => {
event.preventDefault();
try {
const response = await fetch('http://localhost:8000/users/signup', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, username, password }),
});
const data = await response.json();
if (response.ok) {
console.log('User cre ated successfully:', data);
// Handle successful signup (e.g., show success message, redirect, etc.)
} else {
console.error('Error creating user:', data);
// Handle error (e.g., show error message)
}
} catch (error) {
console.error('Error:', error);
// Handle network or other errors
}
};
return (
<div className="signup-container">
<h1>Signup</h1>
<form onSubmit={handleSubmit}>
<div className="form-group">
<label style={{ color: "white" }} htmlFor="name">Name:</label>
<input style={{ backgroundColor: "black", color: "white" }}
type="text"
id="name"
value={name}
onChange={(e) => setName(e.target.value)}
className="form-control"
/>
</div>
<div className="form-group">
<label style={{ color: "white" }} htmlFor="username">Username:</label>
<input style={{ backgroundColor: "black", color: "white" }}
type="text"
id="username"
value={username}
onChange={(e) => setUsername(e.target.value)}
className="form-control"
/>
</div>
<div className="form-group">
<label style={{ color: "white" }} htmlFor="password">Password:</label>
<input style={{ backgroundColor: "black", color: "white" }}
type="password"
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="form-control"
/>
</div>
<button type="submit" className="btn-submit">signup</button>
</form>
</div>
);
}
================================================
FILE: frontend/src/Component/TermsOfService.css
================================================
/* src/components/TermsOfService.css */
/* Basic Reset */
body, h1, h4, p, a {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
}
header {
background: #f8f9fa;
padding: 1rem;
border-bottom: 1px solid #ddd;
}
nav {
display: flex;
justify-content: center;
gap: 1rem;
}
nav a {
text-decoration: none;
margin: 0 1rem;
}
nav a.active {
font-weight: bold;
}
main {
padding: 2rem;
}
.terms-of-service {
max-width: 1140px;
margin: 0 auto;
}
h1 {
font-size: 2rem;
margin-top: 80px;
/* color: black; */
margin-bottom: 1rem;
}
h4 {
font-size: 1.5rem;
margin-top: 1.5rem;
margin-bottom: 0.5rem;
}
p {
margin-bottom: 1rem;
}
================================================
FILE: frontend/src/Component/TermsOfService.js
================================================
import React from 'react';
import './TermsOfService.css';
function TermsOfService() {
return (
<div>
<header>
<nav>
<a href="/">Home</a>
<a href="/privacy-policy">Privacy Policy</a>
<a href="/terms-of-service" className="active">Terms of Service</a>
</nav>
</header>
<main>
<section className="terms-of-service">
<h1>Terms of Service</h1>
<p>Welcome to DevLabs, a website where you can search for free tools that are useful for your daily needs. This application is created by the incredible open-source community. On DevLabs, you can discover a collection of free tools that can assist you in various aspects of your life. Moreover, you have the opportunity to contribute to this project by adding more tools to the database.</p>
<h4>1. Acceptance of Terms</h4>
<p>By accessing or using our website, you agree to comply with and be bound by these Terms of Service. If you do not agree to these terms, please do not use our website.</p>
<h4>2. Changes to Terms</h4>
<p>We reserve the right to modify these Terms of Service at any time. Your continued use of the website after any changes constitutes your acceptance of the new terms.</p>
<h4>3. Use of Website</h4>
<p>You agree to use our website only for lawful purposes and in a manner that does not infringe the rights of or restrict the use of the website by any third party.</p>
<h4>4. User Contributions</h4>
<p>You may contribute to our database by adding new tools. However, all contributions must comply with our guidelines and be approved by our team.</p>
<h4>5. Limitation of Liability</h4>
<p>DevLabs is not responsible for any damages arising from the use or inability to use our website or any content contained within.</p>
<h4>6. Governing Law</h4>
<p>These Terms of Service are governed by and construed in accordance with the laws of the jurisdiction in which we operate.</p>
<h4>7. Contact Us</h4>
<p>If you have any questions about these Terms of Service, please contact us at <a href="mailto:support@devlabsstore.tech">support@devlabsstore.tech</a>.</p>
</section>
</main>
</div>
);
}
export default TermsOfService;
================================================
FILE: frontend/src/Component/TrailingCursor/TrailingCursor.jsx
================================================
// import React, { useEffect, useState } from 'react';
// import Styles from './TrailingCursor.module.css';
// import { PiCursorFill } from "react-icons/pi";
// import { FaHandPointer } from "react-icons/fa";
// import { LuTextCursor } from "react-icons/lu";
// const TrailingCursor = () => {
// const [cursorPosition, setCursorPosition] = useState({ x: 0, y: 0 });
// const [isPointer, setIsPointer] = useState('default');
// const handleMouseMove = (event) => {
// const scrollLeft = window.pageXOffset;
// const scrollTop = window.pageYOffset;
// setCursorPosition({ x: event.clientX + scrollLeft, y: event.clientY + scrollTop });
// createTrailing(event.clientX + 40, event.clientY + 40);
// };
// const handleMouseOver = (event) => {
// if (event.target.tagName === 'A' || event.target.tagName === 'BUTTON') {
// setIsPointer('pointer');
// } else if (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA') {
// setIsPointer('text');
// } else {
// setIsPointer('default');
// }
// };
// const createTrailing = (x, y) => {
// const trailingContainer = document.createElement('div');
// trailingContainer.className = 'trailing-container';
// for (let i = 0; i < 2; i++) {
// const trailing = document.createElement('div');
// trailing.className = Styles['trailing'];
// const relativeX = x + Math.random() * 20 - 10; // Randomize position within a range
// const relativeY = y + Math.random() * 20 - 10; // Randomize position within a range
// trailing.style.left = `${relativeX - 5}px`;
// trailing.style.top = `${relativeY - 5}px`;
// trailingContainer.appendChild(trailing);
// }
// document.body.appendChild(trailingContainer);
// // Remove the trailing elements after the animation ends
// setTimeout(() => {
// trailingContainer.remove();
// }, 400);
// };
// useEffect(() => {
// document.addEventListener('mousemove', handleMouseMove);
// document.addEventListener('mouseover', handleMouseOver);
// return () => {
// document.removeEventListener('mousemove', handleMouseMove);
// document.removeEventListener('mouseover', handleMouseOver);
// };
// }, []);
// return (
// <div>
// <div className={Styles["cursor-container"]}
// style={{
// left: `${cursorPosition.x}px`,
// top: `${cursorPosition.y}px`,
// position: 'absolute',
// }}>
// {isPointer === 'pointer' ? (
// <FaHandPointer className={Styles["custom-cursor"]} />
// ) : (
// isPointer === 'default' ? (
// <PiCursorFill className={Styles["custom-cursor"]} style={{ transform: 'rotate(13deg)' }} />
// ) : (
// <LuTextCursor className={Styles["custom-cursor"]} />
// )
// )}
// </div>
// </div>
// );
// };
// // export default TrailingCursor;
================================================
FILE: frontend/src/Component/TrailingCursor/TrailingCursor.module.css
================================================
/* .cursor-container {
position: absolute;
pointer-events: none;
z-index: 12;
transform: translate(0,10%);
} */
/*
.custom-cursor {
width: 33px;
height: 33px;
color: rgb(153, 0, 255);
transform: translate(0,20%);
}
.trailing-container {
position: absolute;
pointer-events: none;
animation: trailing-animation 0.4s linear;
} */
/* .trailing {
position: absolute;
width: 8px;
height: 8px;
background: linear-gradient(45deg, #d294eb, #8900d3);
border-radius: 50%;
transform: scale(0);
animation: trailing-effect 0.4s linear;
transition: transform 1.2s, opacity 1s;
pointer-events: none;
/* z-index: 9998; */
/* } */
/*
@keyframes trailing-effect {
from {
transform: scale(1);
opacity: 1;
}
to {
transform: scale(3);
opacity: 0;
}
}
@keyframes trailing-animation {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
*/
================================================
FILE: frontend/src/Component/TrailingCursor/index.js
================================================
// index.js in frontend/src/Component/TrailingCursor/
// Importing the TrailingCursor component from its file
// import TrailingCursor from './TrailingCursor';
// Exporting the component to be used in other parts of the application
// export default TrailingCursor;
================================================
FILE: frontend/src/Component/accordion.js
================================================
import { HiShieldCheck } from 'react-icons/hi';
import { MdCancel, MdAnalytics } from 'react-icons/md';
const data = [
{
icon: <HiShieldCheck />,
heading: 'What is DevLabs Store?',
detail:
'DevLabs Store is an online marketplace that offers a wide range of AI and machine learning models, tools, and services. It provides a platform for developers, data scientists, and businesses to buy and sell AI solutions.',
},
{
icon: <MdAnalytics />,
heading: 'How do I get a new tool?',
detail:
'Each tool has a link that you can click to access it and also add it to your bookmarks.',
},
{
icon: <MdCancel />,
heading: 'How do I get started with contributing to DevLabs?',
detail:
"To contribute, go to the GitHub repository, create a new repository, clone the project, and start contributing",
},
];
export default data;
================================================
FILE: frontend/src/DB/openSource.json
================================================
[
{
"projectName": "DevLabs",
"ownerUsername": "HimanshuNarware",
"tags": ["JS", "CSS", "HTML", "React.JS"],
"link": "https://github.com/HimanshuNarware/Devlabs",
"description": "Devlabs is an application that is used to search for free tools that are both free and helpful for our needs."
},
{
"projectName": "Desktop-Assistant",
"ownerUsername": "vihar-s1",
"tags": ["python", "Automation", "Voice-Assistant"],
"link": "https://github.com/vihar-s1/Desktop-Assistant",
"description": "Python-based Voice Assistant to simplify desktop tasks through voice commands."
},
{
"projectName": "Supply Chain Management",
"ownerUsername": "kartikmehta18",
"tags": ["React.JS","Next.JS","Solidity", "Tailwind CSS"],
"link": "https://github.com/kartikmehta18/SupplyChainManagement",
"description": " (DApp) powered by blockchain technology to streamline supply chain management processes."
},
{
"projectName": "PetAdopt",
"ownerUsername": "kartikmehta18",
"tags": ["HTML","JS","CSS", "Bootstrap"],
"link": "https://github.com/kartikmehta18/PetAdopts",
"description": " This is the largest no-kill rescue and pet adoption platform."
},
{
"projectName": "Ciphers",
"ownerUsername": "vihar-s1",
"tags": ["python", "cryptography"],
"link": "https://github.com/vihar-s1/Ciphers",
"description": "Cryptographic Ciphers implemented all at one place."
},
{
"projectName": "Jarvis - Decentralised Expense Tracker",
"ownerUsername": "Joy Almeida",
"tags": [
"TypeScript",
"Next.Js",
"Solidity",
"Ethereum",
"HTML",
"CSS",
"Bootstrap"
],
"link": "https://github.com/J0SAL/Decentralized-Expense-Tracker",
"description": "Web app to assist users in managing and maintaining their transactions using decentralization."
},
{
"projectName": "ProjectsHut",
"ownerUsername": "Priyankar Pal",
"tags": ["React.JS", "Tailwind CSS"],
"link": "https://github.com/priyankarpal/ProjectsHut",
"description": "Platform to showcase work and connect with a global audience."
},
{
"projectName": "Sal-Dapp",
"ownerUsername": "Sal-Dapp",
"tags": ["Web3", "Polygon", "Solidity", "IPFS", "Blockchain"],
"link": "https://github.com/Vikash-8090-Yadav/SaL--dApp",
"description": "Platform to manage and give salaries to employees."
},
{
"projectName": "Face-X",
"ownerUsername": "Akshita Gupta",
"tags": ["ML", "ANN", "CNN", "OpenCV", "Python", "IoT"],
"link": "https://github.com/akshitagupta15june/Face-X",
"description": "Repository of algorithms and operations related to facial recognition."
},
{
"projectName": "Dev Geeks",
"ownerUsername": "Pranjay Poddar",
"tags": ["HTML", "CSS", "JavaScript"],
"link": "https://github.com/pranjay-poddar/Dev-Geeks",
"description": "Collection of projects for learning and improving development skills."
},
{
"projectName": "Moksh",
"ownerUsername": "Akshita Gupta",
"tags": ["HTML", "CSS", "JS", "React.JS", "echo3d"],
"link": "https://github.com/akshitagupta15june/Moksh",
"description": "Spiritual productivity tool to achieve balance in life."
},
{
"projectName": "Stoccoin-Website",
"ownerUsername": "Royal Simpson Pinto",
"tags": ["MongoDB", "Express", "React.JS", "Node.JS"],
"link": "https://github.com/Stoccoin-Official/Stoccoin-Website",
"description": "Web app for trading stocks and crypto, displaying news feeds and real-time data."
},
{
"projectName": "StichHub",
"ownerUsername": "Naresh Chandanbatve",
"tags": ["ReactThreeFibre", "Tailwind CSS", "MERN stack"],
"link": "https://github.com/UBA-GCOEN/StichHub",
"description": "Platform to connect tailors and customers."
},
{
"projectName": "PetMe",
"ownerUsername": "Akshita Gupta",
"tags": ["React.JS", "Node.JS", "HTML", "CSS", "JS"],
"link": "https://github.com/akshitagupta15june/PetMe",
"description": "Platform for animal adoption, donation, and emergency medical care."
},
{
"projectName": "Project-Amupedia",
"ownerUsername": "Anmol Agrawal",
"tags": ["Next.JS", "MongoDB", "Node.JS", "CSS", "HTML", "JS"],
"link": "https://github.com/amupedia2021/Project-Amupedia",
"description": "Project providing notes and assignments to college students."
},
{
"projectName": "CrazyCoder",
"ownerUsername": "Yash Parsana",
"tags": ["Kotlin", "Firebase", "Node.JS", "Express.JS"],
"link": "https://github.com/Yash-Parsana/CrazyCoderApp",
"description": "Competitive programming platform for algorithms, data structures, and Mathematics."
},
{
"projectName": "BlogWeet",
"ownerUsername": "Anjali Kumari Dubey",
"tags": ["JavaScript", "React.JS", "CSS", "Firebase"],
"link": "https://github.com/AKD-01/blogweet",
"description": "Social media app for creating, posting, and sharing blogs."
},
{
"projectName": "ExtraSpace-Cloud",
"ownerUsername": "Ritik Kumar",
"tags": ["React.JS", "JavaScript", "CSS3", "Firebase"],
"link": "https://github.com/srivastavaritik/Extraspace-Cloud",
"description": "Cloud platform for creating folders, uploading files, and links."
},
{
"projectName": "Umatter",
"ownerUsername": "Monalika Patnaik",
"tags": ["HTML", "CSS", "JavaScript", "React", "Bootstrap"],
"link": "https://github.com/MonalikaPatnaik/UMatter",
"description": "Platform to assist individuals in quitting bad habits through personalized sessions."
},
{
"projectName": "Dummygram",
"ownerUsername": "Narayan Soni",
"tags": ["React.JS", "Firebase", "Material-UI", "JavaScript"],
"link": "https://github.com/narayan954/dummygram",
"description": "Instagram clone with features like authentication, comments, and likes."
},
{
"projectName": "Scene - OTT platform",
"ownerUsername": "Sourabh Sikarwar",
"tags": ["React.JS", "Firebase"],
"link": "https://github.com/sourabhsikarwar/Scene-Movie-Platform",
"description": "Movie showcase/OTT platform clone with authentication and other features."
},
{
"projectName": "AEC Library",
"ownerUsername": "Saurav Mukherjee",
"tags": ["HTML", "CSS", "JavaScript", "Bootstrap", "API"],
"link": "https://github.com/SauravMukherjee44/Aec-Library-Website",
"description": "Open-source library website with resources and book donation section."
},
{
"projectName": "Engineering Notes",
"ownerUsername": "Nagesh Mandal",
"tags": ["HTML", "CSS", "JavaScript", "Bootstrap", "JS"],
"link": "https://github.com/NageshMandal/Engineering-Notes-Website",
"description": "Website providing free handwritten notes to engineering students."
},
{
"projectName": "DevEmpire",
"ownerUsername": "Swapnil Srivastava",
"tags": ["Next.JS", "Sass/SCSS"],
"link": "https://github.com/swapnilsparsh/DevEmpire",
"description": "Platform for finding resources and details on ambassador/fellowship programs, events, and toolkits."
},
{
"projectName": "Sampark",
"ownerUsername": "Gaurav Verma",
"tags": ["MERN", "Firebase"],
"link": "https://github.com/Gaurav-Verma07/sampark",
"description": "Sampark is a social platform that connects seekers from orphanages and NGOs with college students who provide assistance and resources related to education, clothes, sanitation and health."
},
{
"projectName": "CropForesight Frontend",
"ownerUsername": "Abhijeet Sinha",
"tags": ["ReactJs", "FastAPI", "Machine Learning"],
"link": "https://github.com/abhijeet141/CropForesight-FrontEnd",
"description": "CropForesight is a crop recommendation website that uses machine learning model to predict the best crop for a given land based on certain parameters."
},
{
"projectName": "CropForesight Backend",
"ownerUsername": "Abhijeet Sinha",
"tags": ["Python"],
"link": "https://github.com/abhijeet141/CropForesight_BackEnd",
"description": "The repository for the backend of the Cropforesight"
},
{
"projectName": "Animating-Buttons",
"ownerUsername": "Om Gawande",
"tags": ["HTML", "CSS", "JS", "JSON", "ReactJS"],
"link": "https://github.com/Spyware007/Animating-Buttons",
"description": "Explore Amazing Buttons animation for your next project."
},
{
"projectName": "Amazing-Python-Scripts",
"ownerUsername": "Avinash Kr. Ranjan",
"tags": [
"Python",
"Jupyter Notebook",
"HTML",
"CSS",
"JavaScript",
"Shell"
],
"link": "https://github.com/avinashkranjan/Amazing-Python-Scripts",
"description": "A curated collection of Amazing Python scripts from Basics to Advance with automation task scripts."
},
{
"projectName": "Friday",
"ownerUsername": "Avinash Kumar Ranjan",
"tags": ["Flutter", "Dart", "Firebase", "Figma"],
"link": "https://github.com/avinashkranjan/Friday",
"description": "Friday - Your Personal Class Manager Assistant, It'll never let you miss another assignment deadline or upcoming test."
},
{
"projectName": "Pentesting-and-Hacking-Scripts",
"ownerUsername": "Avinash Ranjan",
"tags": ["Python", "Shell", "HTML", "CSS", "JS"],
"link": "https://github.com/avinashkranjan/Pentesting-and-Hacking-Scripts",
"description": "A curated collection of Pentesting and Hacking Scripts for Script Kiddie to Advanced Pentesters."
},
{
"projectName": "GyanaGuru",
"ownerUsername": "Piyush Kalyan",
"tags": [
"Next.js",
"React",
"Tailwind CSS",
"Firebase",
"HTML",
"CSS",
"JavaScript",
"Git",
"GitHub",
"VS Code",
"NPM"
],
"link": "https://github.com/PiyushKalyanpy/GyanaGuru",
"description": "The GyanaGuru website is an online learning platform that provides access to high-quality educational resources in a wide range of subjects."
},
{
"projectName": "Bookingjini Icons Pack",
"ownerUsername": "Ashutosh Dash",
"tags": ["HTML", "CSS", "JavaScript", "React", "Figma"],
"link": "https://github.com/Bookingjini-Labs/bookingjini-icons",
"description": "Bookingjini Icons Pack is a collection of 50 icons designed specifically for the hospitality industry."
},
{
"projectName": "3D T-shirt Designer",
"ownerUsername": "Aman Jaiman",
"tags": ["React", "three.js", "tailwindCSS", "express"],
"link": "https://github.com/amanjaiman1/Product_3D",
"description": "https://github.com/amanjaiman1/Product_3D"
},
{
"projectName": "Coding Contests Companion",
"ownerUsername": "Roshan Dash",
"tags": [
"Javascript",
"Node.js",
"Discord.js",
"Puppeteer",
"Axios",
"jsDom",
"MonogDB",
"Moongoose",
"Azure"
],
"link": "https://github.com/roshan1337d/coding-contests-companion",
"description": "Coding Contests Companion is a discord bot for the competitive coding enthusiasts."
},
{
"projectName": "EdgeChains",
"ownerUsername": "Sandeep Srinivasa",
"tags": [
"Java",
"Spring",
"RxJava",
"Spring Lambda",
"Apache TVM Machine Learning Compiler"
],
"link": "https://github.com/arakoodev/edgechains",
"description": "chain-of-thought engineering for LLM and OpenAI GPT"
},
{
"projectName": "Blogzen",
"ownerUsername": "Piyush Gupta",
"tags": ["HTML", "CSS", "JavaScript"],
"link": "https://github.com/DSC-JSS-NOIDA/blogzen",
"description": "A collection of resources categorized by tech domains, languages, expertise and much more. Blogzen gives you quick access to all the resources that you could need at a single place, with a click!"
},
{
"projectName": "ApnaBharat-Bus-Booking-Reservation-System",
"ownerUsername": "Pranjal Agarwal",
"tags": ["Python", "Sqlite3", "Tkinter", "GUI", "Javascript"],
"link": "https://github.com/Pranjal360Agarwal/ApnaBharat-Bus-Booking-Reservation-System",
"description": "Bus Reservation System is a pretty fully functional system developed using Tkinter (GUI), SQLite, Python, which is designed to automate the online ticket purchasing through an easy online bus booking system."
},
{
"projectName": "GitHub Automation scripts",
"ownerUsername": "Sahil Sagwekar",
"tags": ["Python", "Bash", "Git", "GitHub"],
"link": "https://github.com/sahil-sagwekar2652/GitHub-Automation-scripts",
"description": "Bash and Python scripts to automate your Git & GitHub workflow."
},
{
"projectName": "informatician",
"ownerUsername": "Rohan Sharma",
"tags": ["Reactjs", "express js", "nodejs", "mongodb"],
"lin
gitextract_wq4xmcei/ ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── adding-new-tool.yml │ │ ├── bug_report.yml │ │ ├── documentation_update.yml │ │ └── feature_request.yml │ ├── pull_request_template.md │ └── workflows/ │ ├── auto-comment-on-pr-merge.yml │ ├── check_duplicate_tools.yml │ ├── close-old-pr-woc.yml │ ├── close-on-merge.yml │ ├── greetings.yaml │ ├── greetings.yml │ └── restrict_pr.yml ├── .idea/ │ ├── .gitignore │ ├── Devlabs-copy.iml │ ├── Devlabs.iml │ ├── modules.xml │ └── vcs.xml ├── .vscode/ │ └── settings.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── README.md ├── backend/ │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── init/ │ │ └── sampleToolsData.js │ ├── package.json │ ├── readme.md │ ├── server.js │ ├── src/ │ │ ├── app.js │ │ ├── config/ │ │ │ ├── ExpressError.js │ │ │ ├── database.js │ │ │ └── nodemailer.js │ │ ├── controllers/ │ │ │ ├── openSourceController.js │ │ │ ├── specialController.js │ │ │ ├── toolController.js │ │ │ └── userController.js │ │ ├── models/ │ │ │ ├── OpenSource.js │ │ │ ├── Tool.js │ │ │ ├── User.js │ │ │ └── reviewForm.js │ │ └── routes/ │ │ ├── openSource.js │ │ ├── special.js │ │ ├── tools.js │ │ └── user.js │ └── vercel.json ├── docker-compose.yaml ├── frontend/ │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── package.json │ ├── public/ │ │ ├── index.html │ │ ├── manifest.json │ │ └── robots.txt │ └── src/ │ ├── App.css │ ├── App.js │ ├── ChatAssistant/ │ │ ├── Avatar.jsx │ │ ├── ChatAssistant.css │ │ ├── ChatAssistant.jsx │ │ └── UserAvatar.jsx │ ├── ChatBot/ │ │ ├── ActionProvider.jsx │ │ ├── MessageParser.jsx │ │ └── config.jsx │ ├── Component/ │ │ ├── About.js │ │ ├── BackToTopButton.js │ │ ├── BookMark.js │ │ ├── Contact.jsx │ │ ├── Faq.js │ │ ├── Footer.js │ │ ├── Home.js │ │ ├── Login.css │ │ ├── Login.js │ │ ├── Modal.js │ │ ├── Navbar/ │ │ │ ├── Navbar.js │ │ │ ├── NavbarCenter.js │ │ │ ├── NavbarItem.js │ │ │ ├── NavbarLeft.js │ │ │ ├── NavbarRight.js │ │ │ └── Progress.js │ │ ├── NotFound.js │ │ ├── OpenSource.js │ │ ├── Pagination.js │ │ ├── Preloader.js │ │ ├── PrivacyPolicy.css │ │ ├── PrivacyPolicy.js │ │ ├── Profile.js │ │ ├── Rate.css │ │ ├── Rate.jsx │ │ ├── Rateus.js │ │ ├── Register.css │ │ ├── Register.js │ │ ├── Review.js │ │ ├── ScrollToTop.jsx │ │ ├── Sidebar/ │ │ │ ├── Sidebar.js │ │ │ └── SidebarContent.js │ │ ├── Signup.js │ │ ├── TermsOfService.css │ │ ├── TermsOfService.js │ │ ├── TrailingCursor/ │ │ │ ├── TrailingCursor.jsx │ │ │ ├── TrailingCursor.module.css │ │ │ └── index.js │ │ └── accordion.js │ ├── DB/ │ │ ├── openSource.json │ │ └── product.json │ ├── Data.js │ ├── Slice/ │ │ └── DataSlice.js │ ├── Store/ │ │ └── store.js │ ├── index.css │ ├── index.js │ ├── lottie/ │ │ ├── bookmark.json │ │ ├── contact.json │ │ └── pre.json │ ├── pages/ │ │ ├── AI.jsx │ │ ├── BackendTools.jsx │ │ ├── CodingPlatform.jsx │ │ ├── Collaboration.jsx │ │ ├── CoursesPlatform.jsx │ │ ├── EthicalHacking.jsx │ │ ├── Extension.jsx │ │ ├── Extensions.jsx │ │ ├── FrontendTools.jsx │ │ ├── Movie.jsx │ │ ├── Movies.jsx │ │ ├── Productivity.jsx │ │ ├── RemoteJob.jsx │ │ ├── RemoteJobs.jsx │ │ ├── Testimonials.jsx │ │ ├── UI.jsx │ │ └── UserInterface.jsx │ ├── style/ │ │ ├── AI.css │ │ ├── About.css │ │ ├── Animations.css │ │ ├── BackToTopButton.css │ │ ├── BackendTools.css │ │ ├── BookMark.css │ │ ├── CodingPlatform.css │ │ ├── Collaboration.css │ │ ├── Contact.css │ │ ├── Courses.css │ │ ├── EthicalHacking.css │ │ ├── Extension.css │ │ ├── Extensions.css │ │ ├── Footer.css │ │ ├── FrontendTools.css │ │ ├── Home.css │ │ ├── Modal.css │ │ ├── Movie.css │ │ ├── Movies.css │ │ ├── Navbar.css │ │ ├── NotFound.css │ │ ├── OpenSource.css │ │ ├── Pagination.css │ │ ├── Productivity.css │ │ ├── Profile.css │ │ ├── Rateus.css │ │ ├── RemoteJobs.css │ │ ├── Remotejob.css │ │ ├── Review.css │ │ ├── Sidebar.css │ │ ├── Signup.css │ │ ├── Testimonials.module.css │ │ ├── Typography.css │ │ ├── UI.css │ │ ├── UserInterface.css │ │ ├── alert.css │ │ ├── faq.css │ │ ├── preloader.css │ │ └── tooltip.css │ └── utils/ │ └── paginationData.js ├── learn.md └── package.json
SYMBOL INDEX (37 symbols across 30 files)
FILE: backend/init/sampleToolsData.js
function db (line 5) | async function db() {
FILE: backend/src/config/ExpressError.js
class ExpressError (line 1) | class ExpressError extends Error{
method constructor (line 2) | constructor(status,message){
FILE: backend/src/config/database.js
constant DB_URI (line 5) | const DB_URI = process.env.MONGODB_URI || "mongodb://0.0.0.0:27017"
FILE: frontend/src/App.js
function App (line 42) | function App() {
FILE: frontend/src/ChatAssistant/Avatar.jsx
function Avatar (line 5) | function Avatar() {
FILE: frontend/src/ChatAssistant/UserAvatar.jsx
function Avatar (line 5) | function Avatar() {
FILE: frontend/src/Component/About.js
constant FOUNDER (line 5) | const FOUNDER = "HimanshuNarware";
constant LINKEDIN_URL (line 6) | const LINKEDIN_URL = "https://www.linkedin.com/in/HimanshuNarware";
constant CARDS_PER_PAGE (line 7) | const CARDS_PER_PAGE = 12;
function About (line 9) | function About() {
FILE: frontend/src/Component/BackToTopButton.js
function BackToTopButton (line 4) | function BackToTopButton() {
function debounce (line 62) | function debounce(func, wait) {
FILE: frontend/src/Component/BookMark.js
function BookMark (line 9) | function BookMark() {
FILE: frontend/src/Component/Faq.js
function Faq (line 14) | function Faq() {
FILE: frontend/src/Component/Footer.js
function Footer (line 28) | function Footer() {
FILE: frontend/src/Component/Home.js
constant BACKEND (line 12) | const BACKEND = process.env.REACT_APP_BACKEND;
function Home (line 14) | function Home(props) {
FILE: frontend/src/Component/Modal.js
function Modal (line 5) | function Modal({ isOpen, onClose, children }) {
FILE: frontend/src/Component/Navbar/Navbar.js
function Navbar (line 6) | function Navbar(props) {
FILE: frontend/src/Component/Navbar/NavbarCenter.js
function NavbarCenter (line 10) | function NavbarCenter() {
FILE: frontend/src/Component/Navbar/NavbarItem.js
function NavbarItem (line 3) | function NavbarItem({ description, to }) {
FILE: frontend/src/Component/Navbar/NavbarLeft.js
function NavbarLeft (line 4) | function NavbarLeft(props, showSideNav) {
FILE: frontend/src/Component/Navbar/NavbarRight.js
function NavbarRight (line 5) | function NavbarRight({ setSearchQuery }) {
FILE: frontend/src/Component/NotFound.js
function NotFound (line 4) | function NotFound() {
FILE: frontend/src/Component/OpenSource.js
constant BACKEND (line 7) | const BACKEND = process.env.REACT_APP_BACKEND;
FILE: frontend/src/Component/Preloader.js
function Preloader (line 6) | function Preloader() {
FILE: frontend/src/Component/Profile.js
function Profile (line 4) | function Profile() {
FILE: frontend/src/Component/Rateus.js
function RateUsComponent (line 5) | function RateUsComponent({ previousContent }) {
FILE: frontend/src/Component/Review.js
constant BACKEND (line 7) | const BACKEND = process.env.REACT_APP_BACKEND;
function Review (line 8) | function Review() {
FILE: frontend/src/Component/ScrollToTop.jsx
function ScrollToTop (line 3) | function ScrollToTop() {
FILE: frontend/src/Component/Sidebar/Sidebar.js
function Sidebar (line 19) | function Sidebar({ showSideNav }) {
FILE: frontend/src/Component/Sidebar/SidebarContent.js
function SidebarContent (line 2) | function SidebarContent({name,description,active}) {
FILE: frontend/src/Component/Signup.js
function Signup (line 4) | function Signup() {
FILE: frontend/src/Component/TermsOfService.js
function TermsOfService (line 4) | function TermsOfService() {
FILE: frontend/src/Data.js
function Data (line 3) | function Data() {
Condensed preview — 171 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,008K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 804,
"preview": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [u"
},
{
"path": ".github/ISSUE_TEMPLATE/adding-new-tool.yml",
"chars": 1879,
"preview": "name: 🛠️ Adding New Tool\ndescription: Want to add new tool on the Devlabs\ntitle: \"[New Tool]: \"\nbody:\n - type: checkbox"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.yml",
"chars": 1514,
"preview": "name: Bug report 🐞\ndescription: File a bug report\ntitle: \"[Bug]: \"\nbody:\n - type: checkboxes\n id: existing-issue\n "
},
{
"path": ".github/ISSUE_TEMPLATE/documentation_update.yml",
"chars": 1890,
"preview": "name: 📝 Documentation Update\ndescription: Improve Documentation\ntitle: \"[Documentation Update]: \"\nbody:\n - type: checkb"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.yml",
"chars": 1877,
"preview": "name: ✨ Feature Request\ndescription: Suggest a feature\ntitle: \"[Feature Request]: \"\nbody:\n - type: checkboxes\n id: e"
},
{
"path": ".github/pull_request_template.md",
"chars": 960,
"preview": "## Related Issue\n[Cite any related issue(s) this pull request addresses. If none, simply state \"None”]\n\n## Description\n["
},
{
"path": ".github/workflows/auto-comment-on-pr-merge.yml",
"chars": 682,
"preview": "# @format\n\nname: Auto Comment on PR Merge\n\non:\n pull_request:\n types: [closed]\n\njobs:\n comment:\n if: github.even"
},
{
"path": ".github/workflows/check_duplicate_tools.yml",
"chars": 1788,
"preview": "# @format\n\nname: Check for Duplicates and Close Issues on PR Merge\n\non:\n pull_request:\n types: [opened, synchronize,"
},
{
"path": ".github/workflows/close-old-pr-woc.yml",
"chars": 841,
"preview": "# @format\r\n\r\nname: Close Stale PRs\r\n\r\non:\r\n schedule:\r\n - cron: '0 0 * * *' # Runs daily at midnight\r\n pull_request"
},
{
"path": ".github/workflows/close-on-merge.yml",
"chars": 1135,
"preview": "# @format\r\n\r\nname: Close Issues on PR Merge\r\n\r\non:\r\n pull_request:\r\n types: [closed]\r\n\r\njobs:\r\n close-issues:\r\n "
},
{
"path": ".github/workflows/greetings.yaml",
"chars": 581,
"preview": "# @format\n\nname: Greetings\n\non: [pull_request_target, issues]\n\njobs:\n greeting:\n runs-on: ubuntu-latest\n permissi"
},
{
"path": ".github/workflows/greetings.yml",
"chars": 1034,
"preview": "# @format\n\nname: 'Greetings'\n\non:\n fork:\n push:\n branches: [main]\n issues:\n types: [opened]\n pull_request_targ"
},
{
"path": ".github/workflows/restrict_pr.yml",
"chars": 3964,
"preview": "# @format\n\nname: Restrict Contributor to limited contributions in Devlabs\n\non:\n pull_request_target:\n types:\n -"
},
{
"path": ".idea/.gitignore",
"chars": 98,
"preview": "# Default ignored files\n/shelf/\n/workspace.xml\n# Editor-based HTTP Client requests\n/httpRequests/\n"
},
{
"path": ".idea/Devlabs-copy.iml",
"chars": 458,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"WEB_MODULE\" version=\"4\">\n <component name=\"NewModuleRootManager\">\n"
},
{
"path": ".idea/Devlabs.iml",
"chars": 458,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"WEB_MODULE\" version=\"4\">\n <component name=\"NewModuleRootManager\">\n"
},
{
"path": ".idea/modules.xml",
"chars": 266,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"ProjectModuleManager\">\n <modules>\n "
},
{
"path": ".idea/vcs.xml",
"chars": 167,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"VcsDirectoryMappings\">\n <mapping dire"
},
{
"path": ".vscode/settings.json",
"chars": 195,
"preview": "{\n \"git.ignoreLimitWarning\": true,\n \"emmet.includeLanguages\": {\n \"\\\"javascript\\\":\": \"\\\"javascriptreact\\\"\"\n "
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 2039,
"preview": "# Devlabs Code of Conduct\n\nWe, the maintainers and contributors of Devlabs, are committed to providing a friendly, safe,"
},
{
"path": "CONTRIBUTING.md",
"chars": 5984,
"preview": "# Contributing to [Devlabs] 🚀\n\nThank you for considering contributing to [Devlabs]! We appreciate your interest in helpi"
},
{
"path": "README.md",
"chars": 8602,
"preview": "<a id=\"top\"></a>\n<div align=\"center\">\n <h1><img src=\"https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Flue"
},
{
"path": "backend/.dockerignore",
"chars": 49,
"preview": "node_modules\nbuild\n.DS_Store\n.env\n.git\n.gitignore"
},
{
"path": "backend/.gitignore",
"chars": 313,
"preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
},
{
"path": "backend/Dockerfile",
"chars": 127,
"preview": "FROM node:alpine\nWORKDIR /app\nCOPY package.json package-lock.json ./\nRUN npm install\nCOPY . .\nEXPOSE 8000\nCMD [\"npm\", \"s"
},
{
"path": "backend/init/sampleToolsData.js",
"chars": 2373,
"preview": "const mongoose = require(\"mongoose\");\nconst { connectToDB } = require(\"../src/config/database\");\nconst Tool = require(\"."
},
{
"path": "backend/package.json",
"chars": 509,
"preview": "{\n\t\"name\": \"devlabs-backend\",\n\t\"version\": \"1.0.0\",\n\t\"description\": \"A backend for storing data for devlabs web-applicati"
},
{
"path": "backend/readme.md",
"chars": 2475,
"preview": "# DevLabs Backend\n\nWelcome to the backend of DevLabs, the platform that connects users with a collection of free tools f"
},
{
"path": "backend/server.js",
"chars": 261,
"preview": "const app = require(\"./src/app\");\nconst { connectToDB } = require(\"./src/config/database\");\n\nconst port = process.env.PO"
},
{
"path": "backend/src/app.js",
"chars": 745,
"preview": "const bodyParser = require(\"body-parser\");\nconst cors = require(\"cors\");\n\nconst express = require(\"express\");\nconst app "
},
{
"path": "backend/src/config/ExpressError.js",
"chars": 181,
"preview": "class ExpressError extends Error{\n constructor(status,message){\n super()\n this.status = status\n "
},
{
"path": "backend/src/config/database.js",
"chars": 498,
"preview": "const mongoose = require(\"mongoose\");\n\nrequire(\"dotenv\").config();\n\nconst DB_URI = process.env.MONGODB_URI || \"mongodb:/"
},
{
"path": "backend/src/config/nodemailer.js",
"chars": 415,
"preview": "const nodemailer = require(\"nodemailer\");\nrequire(\"dotenv\").config();\n\nconst transporter = nodemailer.createTransport({\n"
},
{
"path": "backend/src/controllers/openSourceController.js",
"chars": 1526,
"preview": "const OpenSource = require(\"../models/OpenSource\");\nrequire(\"dotenv\").config();\n\nconst addProject = async (req, res) => "
},
{
"path": "backend/src/controllers/specialController.js",
"chars": 1885,
"preview": "const mongoose = require(\"mongoose\")\nconst reviewForm = require(\"../models/reviewForm\");\n\nconst {transporter, mailOption"
},
{
"path": "backend/src/controllers/toolController.js",
"chars": 1010,
"preview": "const Tool = require(\"../models/Tool\");\nrequire(\"dotenv\").config();\n\nconst addTool = async (req, res) => {\n try {\n "
},
{
"path": "backend/src/controllers/userController.js",
"chars": 2501,
"preview": "const User = require(\"../models/User\");\nconst passwordHash = require(\"password-hash\");\nconst jwt = require(\"jsonwebtoken"
},
{
"path": "backend/src/models/OpenSource.js",
"chars": 523,
"preview": "const mongoose = require(\"mongoose\");\n\nconst OpenSourceSchema = new mongoose.Schema({\n projectName: {\n type: S"
},
{
"path": "backend/src/models/Tool.js",
"chars": 633,
"preview": "const mongoose = require(\"mongoose\");\n\nconst ToolSchema = new mongoose.Schema({\n productName: {\n type: String,"
},
{
"path": "backend/src/models/User.js",
"chars": 433,
"preview": "const mongoose = require(\"mongoose\");\n\nconst userSchema = new mongoose.Schema({\n name: {\n type: String,\n required"
},
{
"path": "backend/src/models/reviewForm.js",
"chars": 348,
"preview": "const mongoose = require(\"mongoose\");\n\nconst reviewFormSchema = new mongoose.Schema({\n name: {\n type: String,\n"
},
{
"path": "backend/src/routes/openSource.js",
"chars": 286,
"preview": "const express = require(\"express\");\nconst router = express.Router();\n\nconst openSourceController = require(\"../controlle"
},
{
"path": "backend/src/routes/special.js",
"chars": 245,
"preview": "const express = require(\"express\");\nconst router = express.Router();\nrequire(\"dotenv\").config();\n\nconst specialControlle"
},
{
"path": "backend/src/routes/tools.js",
"chars": 256,
"preview": "const express = require(\"express\");\nconst router = express.Router();\n\nconst toolController = require(\"../controllers/too"
},
{
"path": "backend/src/routes/user.js",
"chars": 438,
"preview": "const express = require(\"express\");\nconst {\n newUser,\n signIn,\n addBookmark,\n} = require(\"../controllers/userControll"
},
{
"path": "backend/vercel.json",
"chars": 253,
"preview": "{\n \"version\": 2,\n \"builds\": [\n {\n \"src\": \"server.js\",\n \"use\": \"@vercel/node\"\n "
},
{
"path": "docker-compose.yaml",
"chars": 436,
"preview": "version: '3.8'\n\nservices:\n devlab-frontend:\n build:\n context: ./frontend\n ports:\n - \"3000:3000\"\n env"
},
{
"path": "frontend/.dockerignore",
"chars": 49,
"preview": "node_modules\nbuild\n.DS_Store\n.env\n.git\n.gitignore"
},
{
"path": "frontend/.gitignore",
"chars": 331,
"preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
},
{
"path": "frontend/Dockerfile",
"chars": 378,
"preview": "# Build stage\nFROM node:alpine AS builder\nWORKDIR /app\nCOPY package.json package-lock.json ./\nRUN npm install\nCOPY . .\nR"
},
{
"path": "frontend/package.json",
"chars": 2326,
"preview": "{\n \"name\": \"myapp\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"dependencies\": {\n \"@babel/plugin-transform-class-pro"
},
{
"path": "frontend/public/index.html",
"chars": 3778,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <link rel=\"icon\" href=\"%PUBLIC_URL%/favicon.i"
},
{
"path": "frontend/public/manifest.json",
"chars": 500,
"preview": "{\n \"short_name\": \"React App\",\n \"name\": \"Create React App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n "
},
{
"path": "frontend/public/robots.txt",
"chars": 67,
"preview": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n"
},
{
"path": "frontend/src/App.css",
"chars": 169,
"preview": ".sidebar-content {\n padding: 10px;\n cursor: pointer;\n \n transition: background-color 0.2s;\n} \n \n /* cursor: pointer"
},
{
"path": "frontend/src/App.js",
"chars": 3637,
"preview": "import React, { useState, useEffect, lazy, Suspense } from \"react\";\nimport { Route, Routes } from \"react-router-dom\";\nim"
},
{
"path": "frontend/src/ChatAssistant/Avatar.jsx",
"chars": 298,
"preview": "import chatbotLogo from \"../assets/chatbotLogo.jpeg\"\nimport React from 'react'\nimport \"../ChatAssistant/ChatAssistant.cs"
},
{
"path": "frontend/src/ChatAssistant/ChatAssistant.css",
"chars": 3978,
"preview": ".chatbot {\n position: fixed;\n bottom: 70px;\n right: 70px;\n margin-right: 20px;\n margin-bottom: 12px;\n /* z-index: "
},
{
"path": "frontend/src/ChatAssistant/ChatAssistant.jsx",
"chars": 1483,
"preview": "import React, { useState } from \"react\";\nimport Chatbot from \"react-chatbot-kit\";\nimport \"react-chatbot-kit/build/main.c"
},
{
"path": "frontend/src/ChatAssistant/UserAvatar.jsx",
"chars": 298,
"preview": "import userAvatar from \"../assets/userAvatar.jpg\"\nimport React from 'react'\nimport \"../ChatAssistant/ChatAssistant.css\"\n"
},
{
"path": "frontend/src/ChatBot/ActionProvider.jsx",
"chars": 1913,
"preview": "import React from 'react';\nimport { createChatBotMessage } from 'react-chatbot-kit';\n\nconst ActionProvider = ({ setState"
},
{
"path": "frontend/src/ChatBot/MessageParser.jsx",
"chars": 2109,
"preview": "import React from \"react\";\n\nconst MessageParser = ({ children, actions }) => {\n const parse = (message) => {\n if(!me"
},
{
"path": "frontend/src/ChatBot/config.jsx",
"chars": 825,
"preview": "import { createChatBotMessage } from 'react-chatbot-kit';\nimport Avatar from \"../ChatAssistant/Avatar\";\nimport UserAvata"
},
{
"path": "frontend/src/Component/About.js",
"chars": 6902,
"preview": "import React, { useState, useEffect } from \"react\";\nimport \"../style/About.css\";\nimport Pagination from \"./Pagination\";\n"
},
{
"path": "frontend/src/Component/BackToTopButton.js",
"chars": 2565,
"preview": "import React, { useState, useEffect } from 'react';\nimport '../style/BackToTopButton.css';\nimport { MdKeyboardDoubleArro"
},
{
"path": "frontend/src/Component/BookMark.js",
"chars": 3914,
"preview": "import React, { useState, useEffect } from \"react\";\nimport { useSelector, useDispatch } from \"react-redux\";\nimport { del"
},
{
"path": "frontend/src/Component/Contact.jsx",
"chars": 5085,
"preview": "import {\n faFacebook,\n faGithub,\n faLinkedin,\n faTwitter,\n} from \"@fortawesome/free-brands-svg-icons\";\nimport { Font"
},
{
"path": "frontend/src/Component/Faq.js",
"chars": 2683,
"preview": "import React, { useState } from \"react\";\r\nimport \"../style/faq.css\";\r\nimport {\r\n Accordion, \r\n AccordionItem,\r\n Accor"
},
{
"path": "frontend/src/Component/Footer.js",
"chars": 8543,
"preview": "import React from \"react\";\nimport logo from \"../image/logo1.png\";\nimport \"../style/Footer.css\";\nimport {\n FaGithubSquar"
},
{
"path": "frontend/src/Component/Home.js",
"chars": 8564,
"preview": "import axios from \"axios\";\nimport React, { useEffect, useState, useRef } from \"react\";\nimport { useDispatch } from \"reac"
},
{
"path": "frontend/src/Component/Login.css",
"chars": 810,
"preview": "/* src/Component/Login.css */\n.login-container {\n display: flex;\n flex-direction: column;\n align-items: center;"
},
{
"path": "frontend/src/Component/Login.js",
"chars": 1101,
"preview": "import React, { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport './Login.css'; // Add yo"
},
{
"path": "frontend/src/Component/Modal.js",
"chars": 414,
"preview": "// Modal.jsx\nimport React from 'react';\nimport \"./../style/Modal.css\";\n\nfunction Modal({ isOpen, onClose, children }) {\n"
},
{
"path": "frontend/src/Component/Navbar/Navbar.js",
"chars": 749,
"preview": "import React, { useState } from \"react\";\nimport \"../../style/Navbar.css\";\nimport Sidebar from \"../Sidebar/Sidebar\";\nimpo"
},
{
"path": "frontend/src/Component/Navbar/NavbarCenter.js",
"chars": 2127,
"preview": "import React, { useState } from \"react\";\nimport { useSelector } from \"react-redux\";\nimport \"../../style/Navbar.css\";\nimp"
},
{
"path": "frontend/src/Component/Navbar/NavbarItem.js",
"chars": 268,
"preview": "import React from \"react\";\nimport { Link } from \"react-router-dom\";\nfunction NavbarItem({ description, to }) {\n return "
},
{
"path": "frontend/src/Component/Navbar/NavbarLeft.js",
"chars": 1314,
"preview": "import React, { useEffect } from \"react\";\nimport \"../../style/Navbar.css\"\nimport logo from \"../../image/logo1.png\";\nfunc"
},
{
"path": "frontend/src/Component/Navbar/NavbarRight.js",
"chars": 1871,
"preview": "import React, { useEffect, useState } from \"react\";\nimport { BsSearch } from \"react-icons/bs\";\nimport { RxCross2 } from "
},
{
"path": "frontend/src/Component/Navbar/Progress.js",
"chars": 517,
"preview": "import React from 'react'\nimport \"../../style/Navbar.css\"\nconst Progress = () => {\n window.onscroll = function () {\n "
},
{
"path": "frontend/src/Component/NotFound.js",
"chars": 780,
"preview": "import React from \"react\";\nimport { Link } from \"react-router-dom\";\nimport \"../style/NotFound.css\"; \nfunction NotFound()"
},
{
"path": "frontend/src/Component/OpenSource.js",
"chars": 4354,
"preview": "import React, { useState, useEffect } from \"react\";\nimport \"../style/OpenSource.css\";\nimport ReactPaginate from \"react-p"
},
{
"path": "frontend/src/Component/Pagination.js",
"chars": 1331,
"preview": "import React from 'react'\nimport \"../style/Pagination.css\"\n\nconst Pagination = ({\n firstCardIndex,\n lastCardIndex,\n d"
},
{
"path": "frontend/src/Component/Preloader.js",
"chars": 647,
"preview": "import React ,{useState,useEffect} from 'react';\nimport '../style/preloader.css';\nimport pre from '../lottie/pre.json'\ni"
},
{
"path": "frontend/src/Component/PrivacyPolicy.css",
"chars": 912,
"preview": "/* PrivacyPolicy.css */\n\n.privacy-policy-container {\n padding: 20px;\n max-width: 800px;\n margin: 0 auto;\n fo"
},
{
"path": "frontend/src/Component/PrivacyPolicy.js",
"chars": 2276,
"preview": "import React from 'react';\nimport './PrivacyPolicy.css';\n\nconst PrivacyPolicy = () => {\n return (\n <div className=\"p"
},
{
"path": "frontend/src/Component/Profile.js",
"chars": 10166,
"preview": "import React, { useEffect, useState } from \"react\";\nimport \"../style/Profile.css\";\n\nfunction Profile() {\n const [profil"
},
{
"path": "frontend/src/Component/Rate.css",
"chars": 121,
"preview": "input[type=radio]{\n display: none;\n}\n\n.Rate .star{\n cursor: pointer;\n}\n.star FaStar{\n border: 1px solid #fff;\n}"
},
{
"path": "frontend/src/Component/Rate.jsx",
"chars": 896,
"preview": "import React, { useState } from 'react'\nimport { FaStar } from 'react-icons/fa'\nimport \"./Rate.css\"\nconst Rate = () => {"
},
{
"path": "frontend/src/Component/Rateus.js",
"chars": 1805,
"preview": "import React, { useState } from \"react\";\nimport { ToastContainer, toast } from \"react-toastify\";\nimport \"react-toastify/"
},
{
"path": "frontend/src/Component/Register.css",
"chars": 816,
"preview": "/* src/Component/Register.css */\n.register-container {\n display: flex;\n flex-direction: column;\n align-items: c"
},
{
"path": "frontend/src/Component/Register.js",
"chars": 1480,
"preview": "import React, { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport './Register.css'; // Add"
},
{
"path": "frontend/src/Component/Review.js",
"chars": 4626,
"preview": "import React, { useState } from \"react\";\nimport ClipLoader from \"react-spinners/ClipLoader\";\nimport \"../style/Review.css"
},
{
"path": "frontend/src/Component/ScrollToTop.jsx",
"chars": 247,
"preview": "import {useEffect} from 'react'\nimport { useLocation } from 'react-router-dom'\nfunction ScrollToTop() {\n const { pathna"
},
{
"path": "frontend/src/Component/Sidebar/Sidebar.js",
"chars": 4232,
"preview": "import React from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { BsBookmark } from \"react-icons/bs\";\nimport "
},
{
"path": "frontend/src/Component/Sidebar/SidebarContent.js",
"chars": 502,
"preview": "import React from \"react\";\nfunction SidebarContent({name,description,active}) {\n function handleSidebarClick(prop) {\n "
},
{
"path": "frontend/src/Component/Signup.js",
"chars": 2412,
"preview": "import React, { useState } from 'react';\nimport '../style/Signup.css'; // Import CSS file for styling\n\nexport default fu"
},
{
"path": "frontend/src/Component/TermsOfService.css",
"chars": 862,
"preview": "/* src/components/TermsOfService.css */\n\n/* Basic Reset */\nbody, h1, h4, p, a {\n margin: 0;\n padding: 0;\n box-s"
},
{
"path": "frontend/src/Component/TermsOfService.js",
"chars": 2354,
"preview": "import React from 'react';\nimport './TermsOfService.css';\n\nfunction TermsOfService() {\n return (\n <div>\n <heade"
},
{
"path": "frontend/src/Component/TrailingCursor/TrailingCursor.jsx",
"chars": 3308,
"preview": "// import React, { useEffect, useState } from 'react';\n// import Styles from './TrailingCursor.module.css';\n// import { "
},
{
"path": "frontend/src/Component/TrailingCursor/TrailingCursor.module.css",
"chars": 908,
"preview": "/* .cursor-container {\n position: absolute;\n pointer-events: none;\n z-index: 12;\n transform: translate(0,10%); \n} */"
},
{
"path": "frontend/src/Component/TrailingCursor/index.js",
"chars": 268,
"preview": "// index.js in frontend/src/Component/TrailingCursor/\n\n// Importing the TrailingCursor component from its file\n// import"
},
{
"path": "frontend/src/Component/accordion.js",
"chars": 903,
"preview": "import { HiShieldCheck } from 'react-icons/hi';\r\nimport { MdCancel, MdAnalytics } from 'react-icons/md';\r\nconst data = ["
},
{
"path": "frontend/src/DB/openSource.json",
"chars": 36384,
"preview": "[\n {\n \"projectName\": \"DevLabs\",\n \"ownerUsername\": \"HimanshuNarware\",\n \"tags\": [\"JS\", \"CSS\", \"HTM"
},
{
"path": "frontend/src/DB/product.json",
"chars": 306825,
"preview": "[\n {\n \"productName\": \"iTerm2\",\n \"category\": \"Tool\",\n \"image\": \"https://iterm2.com/img/logo2x.jpg\",\n \"link\":"
},
{
"path": "frontend/src/Data.js",
"chars": 102,
"preview": "import React from 'react'\n\nfunction Data() {\n return (\n <div>Data</div>\n )\n}\n\nexport default Data"
},
{
"path": "frontend/src/Slice/DataSlice.js",
"chars": 943,
"preview": "import { createSlice } from \"@reduxjs/toolkit\";\n\n// Helper function to get initial bookmarks from local storage\nconst ge"
},
{
"path": "frontend/src/Store/store.js",
"chars": 175,
"preview": "import { configureStore } from \"@reduxjs/toolkit\";\nimport SourceReducer from '../Slice/DataSlice'\n\nexport default config"
},
{
"path": "frontend/src/index.css",
"chars": 1176,
"preview": ":root,\nbody,\nhtml {\n scrollbar-width: none;\n height: 100%;\n /* cursor: none; */\n}\n* {\n margin: 0;\n padding: 0;\n bo"
},
{
"path": "frontend/src/index.js",
"chars": 881,
"preview": "import React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport \"./index.css\";\nimport { Provider } from \"react-redux"
},
{
"path": "frontend/src/lottie/bookmark.json",
"chars": 22176,
"preview": "{\"v\":\"4.10.0\",\"fr\":30,\"ip\":0,\"op\":50,\"w\":200,\"h\":200,\"nm\":\"bookmark\",\"ddd\":0,\"assets\":[],\"layers\":[{\"ddd\":0,\"ind\":1,\"ty\""
},
{
"path": "frontend/src/lottie/contact.json",
"chars": 142387,
"preview": "{\"nm\":\"customer-support\",\"ddd\":0,\"h\":500,\"w\":500,\"meta\":{\"g\":\"@lottiefiles/toolkit-js 0.33.2\"},\"layers\":[{\"ty\":4,\"nm\":\"C"
},
{
"path": "frontend/src/lottie/pre.json",
"chars": 8342,
"preview": "{\"v\":\"5.5.8\",\"fr\":50,\"ip\":0,\"op\":147,\"w\":800,\"h\":600,\"nm\":\"Paperplane\",\"ddd\":0,\"assets\":[{\"id\":\"comp_0\",\"layers\":[{\"ddd\""
},
{
"path": "frontend/src/pages/AI.jsx",
"chars": 2942,
"preview": "import React from \"react\";\nimport \"../style/AI.css\";\n\nconst AI = () => {\n const blogs = [\n {\n title: \"Introduct"
},
{
"path": "frontend/src/pages/BackendTools.jsx",
"chars": 4242,
"preview": "import React from 'react'\nimport \"../style/BackendTools.css\"\nconst tools = [\n {\n name: \"Node.js\",\n descript"
},
{
"path": "frontend/src/pages/CodingPlatform.jsx",
"chars": 6392,
"preview": "import React from \"react\";\nimport \"../style/CodingPlatform.css\";\n\nconst tools = [\n {\n name: \"CodeSandbox\",\n descr"
},
{
"path": "frontend/src/pages/Collaboration.jsx",
"chars": 8681,
"preview": "import React from 'react'\nimport '../style/Collaboration.css'\nconst movies = [\n {\n title: \"Google Drive\",\n catego"
},
{
"path": "frontend/src/pages/CoursesPlatform.jsx",
"chars": 4192,
"preview": "import React from 'react';\nimport '../style/Courses.css'; \n\nconst courses = [\n {\n title: \"Introduction to Progra"
},
{
"path": "frontend/src/pages/EthicalHacking.jsx",
"chars": 2482,
"preview": "import React from 'react';\nimport '../style/EthicalHacking.css';\nconst blogs = [\n {\n title: 'Introduction to Ethical"
},
{
"path": "frontend/src/pages/Extension.jsx",
"chars": 4001,
"preview": "import React from \"react\";\nimport \"../style/Extensions.css\";\n\nconst extensions = [\n {\n title: \"React Developer Tools"
},
{
"path": "frontend/src/pages/Extensions.jsx",
"chars": 4249,
"preview": "import React from \"react\";\nimport \"../style/Extension.css\";\n\nconst extensions = [\n { name: \"Usersnap Chrome extension\","
},
{
"path": "frontend/src/pages/FrontendTools.jsx",
"chars": 7187,
"preview": "import React from \"react\";\nimport \"../style/FrontendTools.css\";\n\nconst tools = [\n { \n name: \"React\", \n descriptio"
},
{
"path": "frontend/src/pages/Movie.jsx",
"chars": 5150,
"preview": "import React from \"react\";\nimport \"../style/Movie.css\";\nconst movies = [\n {\n title: \"The Pursuit of Happyness\",\n "
},
{
"path": "frontend/src/pages/Movies.jsx",
"chars": 26640,
"preview": "import React from \"react\";\nimport \"../style/Movies.css\";\n\nconst movies = [\n { name: \"Netflix\", description: \"Netflix is"
},
{
"path": "frontend/src/pages/Productivity.jsx",
"chars": 4966,
"preview": "import React from 'react'\nimport '../style/Productivity.css'\nconst products = [\n {\n title: \"Asana\",\n category: \"P"
},
{
"path": "frontend/src/pages/RemoteJob.jsx",
"chars": 17002,
"preview": "import React from \"react\";\nimport \"../style/Remotejob.css\";\n\nconst jobs = [\n { name: \"FLEXJOBS\", description: \"FlexJobs"
},
{
"path": "frontend/src/pages/RemoteJobs.jsx",
"chars": 2914,
"preview": "import React from \"react\";\nimport \"../style/RemoteJobs.css\";\n\nconst tools = [\n { name: \"Toptal\", \n description: \"Top"
},
{
"path": "frontend/src/pages/Testimonials.jsx",
"chars": 2893,
"preview": "import React, { useState } from 'react';\nimport styles from '../style/Testimonials.module.css';\nimport test1 from '../im"
},
{
"path": "frontend/src/pages/UI.jsx",
"chars": 18976,
"preview": "import React from \"react\";\nimport \"../style/UI.css\";\n\nconst UI = () => {\n const blogs = [\n {\n title: \"Introduct"
},
{
"path": "frontend/src/pages/UserInterface.jsx",
"chars": 4671,
"preview": "import React from \"react\";\nimport \"../style/UserInterface.css\";\nconst design = [\n { name: \"Onsen UI\", description: \"Ons"
},
{
"path": "frontend/src/style/AI.css",
"chars": 881,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f4f4f4;\n}\n.container {\n max-wi"
},
{
"path": "frontend/src/style/About.css",
"chars": 9288,
"preview": "\n.about__contributor-container {\n gap: 5%;\n /* margin: 40px; */\n font-size: 2rem;\n margin-top: 6rem;\n width: 100%;\n"
},
{
"path": "frontend/src/style/Animations.css",
"chars": 142,
"preview": "/* Animations.css */\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n.fade-in {\n animation: fad"
},
{
"path": "frontend/src/style/BackToTopButton.css",
"chars": 1489,
"preview": ".back-to-top-button {\n position: fixed;\n bottom: 80px;\n right: 20px;\n z-index: 10;\n display: none;\n ba"
},
{
"path": "frontend/src/style/BackendTools.css",
"chars": 1452,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f4f4f4;\n }\n .frontend"
},
{
"path": "frontend/src/style/BookMark.css",
"chars": 3671,
"preview": ".bookmark {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n width: 100vw;"
},
{
"path": "frontend/src/style/CodingPlatform.css",
"chars": 1733,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f4f4f4;\n}\n.coding-platform {\n "
},
{
"path": "frontend/src/style/Collaboration.css",
"chars": 1163,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f0f0f0;\n }\n .containe"
},
{
"path": "frontend/src/style/Contact.css",
"chars": 3899,
"preview": "/* .outer-contact {\n margin: 0;\n padding: 0;\n font-family: Arial, sans-serif;\n overflow-x: hidden;\n} */\n.contact-con"
},
{
"path": "frontend/src/style/Courses.css",
"chars": 923,
"preview": "/* EthicalHacking.css */\nbody {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #161313"
},
{
"path": "frontend/src/style/EthicalHacking.css",
"chars": 1064,
"preview": "/* EthicalHacking.css */\n\nbody {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color"
},
{
"path": "frontend/src/style/Extension.css",
"chars": 1981,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f4f4f4;\n }\n\n .extensi"
},
{
"path": "frontend/src/style/Extensions.css",
"chars": 974,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f0f0f0;\n}\n.container {\n max-wi"
},
{
"path": "frontend/src/style/Footer.css",
"chars": 6664,
"preview": ".Footer {\n padding: 5rem 0;\n /* margin-top: 5rem; */\n background: #6a43c3;\n color: white;\n}\n/* Social Icons Hover E"
},
{
"path": "frontend/src/style/FrontendTools.css",
"chars": 1613,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f4f4f4;\n }\n .frontend"
},
{
"path": "frontend/src/style/Home.css",
"chars": 12361,
"preview": "/* hero section starts */\n.hero {\n margin-top: 1rem;\n max-width: 100vw;\n width: 100%;\n z-index: 0; \n min-height: 10"
},
{
"path": "frontend/src/style/Modal.css",
"chars": 801,
"preview": ".modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0; \n bottom: 0;\n background: rgba(239, 234, 234, 0.7"
},
{
"path": "frontend/src/style/Movie.css",
"chars": 1166,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f0f0f0;\n }\n \n .conta"
},
{
"path": "frontend/src/style/Movies.css",
"chars": 1920,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f4f4f4;\n }\n\n .movies "
},
{
"path": "frontend/src/style/Navbar.css",
"chars": 8686,
"preview": ".navbar {\n background-color: #8b5cf6;\n padding: 5px 10px; /* Decreased padding to reduce height */\n position: fixed;\n"
},
{
"path": "frontend/src/style/NotFound.css",
"chars": 836,
"preview": ".not-found-container {\n display: flex;\n justify-content: center;\n align-items: center;\n /* height: 100vh; */"
},
{
"path": "frontend/src/style/OpenSource.css",
"chars": 4541,
"preview": ".open-source__page-container {\n width: 100vw;\n /* Ensure it covers the entire viewport width */\n display: flex;"
},
{
"path": "frontend/src/style/Pagination.css",
"chars": 1176,
"preview": "nav {\n max-width: fit-content;\n margin: 0 auto;\n padding: 0 10px;\n}\n\n.active>.page-link{\n z-index: 0;\n}\n\n/* .paginat"
},
{
"path": "frontend/src/style/Productivity.css",
"chars": 1163,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f0f0f0;\n }\n \n .conta"
},
{
"path": "frontend/src/style/Profile.css",
"chars": 6246,
"preview": "/* Auth Form Styles */\n.auth__container {\n max-width: 600px;\n margin: 30px auto;\n font-family: Arial, sans-serif;\n b"
},
{
"path": "frontend/src/style/Rateus.css",
"chars": 1817,
"preview": ".rate-us-page {\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n.toast-success {\n background-colo"
},
{
"path": "frontend/src/style/RemoteJobs.css",
"chars": 1431,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f4f4f4;\n}\n\n.remote-jobs"
},
{
"path": "frontend/src/style/Remotejob.css",
"chars": 1919,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f4f4f4;\n }\n \n .remot"
},
{
"path": "frontend/src/style/Review.css",
"chars": 1651,
"preview": ".review__form {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n "
},
{
"path": "frontend/src/style/Sidebar.css",
"chars": 3759,
"preview": "\n.sidebar-content {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: flex-start;"
},
{
"path": "frontend/src/style/Signup.css",
"chars": 1136,
"preview": ".signup-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 30px;\n background-colo"
},
{
"path": "frontend/src/style/Testimonials.module.css",
"chars": 2141,
"preview": ".testimonials {\n text-align: center;\n margin: 50px auto 20px auto; /* Reduced bottom margin to 20px */\n max-width: 90"
},
{
"path": "frontend/src/style/Typography.css",
"chars": 1910,
"preview": "/* Typography.css */\n\n/* Import custom fonts */\n@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;70"
},
{
"path": "frontend/src/style/UI.css",
"chars": 1003,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f4f4f4;\n }\n \n .conta"
},
{
"path": "frontend/src/style/UserInterface.css",
"chars": 1935,
"preview": "body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f4f4f4;\n }\n\n .ui-desi"
},
{
"path": "frontend/src/style/alert.css",
"chars": 592,
"preview": "/* alert.css */\n\n/* Base styles for alerts */\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid trans"
},
{
"path": "frontend/src/style/faq.css",
"chars": 2771,
"preview": ".faq {\r\n margin-top: 7rem;\r\n margin-bottom: 1rem;\r\n padding-left: 0.5rem;\r\n padding-right: 0.5rem;\r\n display: flex;"
},
{
"path": "frontend/src/style/preloader.css",
"chars": 86,
"preview": ".pre{\n display: flex;\n align-items: center;\n justify-content: center;\n } \n "
},
{
"path": "frontend/src/style/tooltip.css",
"chars": 0,
"preview": ""
},
{
"path": "frontend/src/utils/paginationData.js",
"chars": 855,
"preview": "export const getPaginationData = (currentPage, cardsPerPage, data) => {\n const lastCardIndex = currentPage * cardsPerPa"
},
{
"path": "learn.md",
"chars": 2024,
"preview": "# How to Build DevLabs: Step-by-Step Guide\nWelcome to the step-by-step guide on building DevLabs! In this tutorial, you'"
},
{
"path": "package.json",
"chars": 1120,
"preview": "{\n \"name\": \"devlabs\",\n \"version\": \"1.0.0\",\n \"description\": \"<div align=\\\"center\\\">\\r <h1><img src=\\\"https://raw.git"
}
]
About this extraction
This page contains the full source code of the HimanshuNarware/Devlabs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 171 files (899.1 KB), approximately 326.2k tokens, and a symbol index with 37 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.