Compare commits

..

5 Commits

Author SHA1 Message Date
Arik Chakma
3ceab552f6 feat: project listing 2024-08-28 08:06:28 +06:00
Arik Chakma
e39fadb032 fix: responsiveness share button 2024-08-28 06:32:28 +06:00
Arik Chakma
8f6cdff0d8 fix: step count issue 2024-08-27 10:22:19 +06:00
Arik Chakma
018a8d6f0f feat: share solution modal 2024-08-27 09:51:10 +06:00
Arik Chakma
7da86f173b wip: implement success modal 2024-08-27 07:21:36 +06:00
407 changed files with 4108 additions and 5801 deletions

View File

@@ -3,6 +3,6 @@
"enabled": false
},
"_variables": {
"lastUpdateCheck": 1724925726721
"lastUpdateCheck": 1723855511353
}
}

1
.astro/types.d.ts vendored
View File

@@ -1 +0,0 @@
/// <reference types="astro/client" />

View File

@@ -1,16 +0,0 @@
name: Clears API Cloudfront Cache
on:
workflow_dispatch:
jobs:
aws_costs:
runs-on: ubuntu-latest
steps:
- name: Clear Cloudfront Caching
run: |
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GH_PAT }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/roadmapsh/infra-ansible/actions/workflows/playbook.yml/dispatches \
-d '{ "ref":"master", "inputs": { "playbook": "roadmap_web.yml", "tags": "cloudfront-api", "is_verbose": false } }'

View File

@@ -1,4 +1,4 @@
name: Clears Frontend Cloudfront Cache
name: Clears Cloudfront Cache
on:
workflow_dispatch:
jobs:

View File

@@ -1,26 +1,24 @@
name: Deploy to EC2
on:
workflow_dispatch:
workflow_dispatch: # allow manual run
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v2
with:
fetch-depth: 2
- uses: actions/setup-node@v4
- uses: actions/setup-node@v1
with:
node-version: 20
- uses: pnpm/action-setup@v4.0.0
- uses: pnpm/action-setup@v3.0.0
with:
version: 9
version: 8.15.6
# -------------------
# --------------------
# Setup configuration
# -------------------
# --------------------
- name: Prepare configuration files
run: |
git clone https://${{ secrets.GH_PAT }}@github.com/roadmapsh/infra-config.git configuration --depth 1
@@ -28,14 +26,13 @@ jobs:
run: |
cp configuration/dist/github/developer-roadmap.env .env
# -----------------
# Prepare the Build
# -----------------
- name: Install Dependencies
# --------------------
# Prepare the build
# --------------------
- name: Install dependencies
run: |
pnpm install
- name: Generate Production Build
- name: Generate build
run: |
git clone https://${{ secrets.GH_PAT }}@github.com/roadmapsh/web-draw.git .temp/web-draw --depth 1
npm run generate-renderer
@@ -48,7 +45,7 @@ jobs:
- uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.EC2_PRIVATE_KEY }}
- name: Deploy Application to EC2
- name: Deploy app to EC2
run: |
rsync -apvz --delete --no-times --exclude "configuration" -e "ssh -o StrictHostKeyChecking=no" -p ./ ${{ secrets.EC2_USERNAME }}@${{ secrets.EC2_HOST }}:/var/www/roadmap.sh/
- name: Restart PM2
@@ -61,9 +58,9 @@ jobs:
cd /var/www/roadmap.sh
sudo pm2 restart web-roadmap
# ----------------------
# --------------------
# Clear cloudfront cache
# ----------------------
# --------------------
- name: Clear Cloudfront Caching
run: |
curl -L \

View File

@@ -1,15 +1,13 @@
name: Label Issue
on:
issues:
types: [ opened, edited ]
jobs:
label-topic-change-issue:
runs-on: ubuntu-latest
steps:
- name: Add Labels To Issue
uses: actions/github-script@v7
- name: Add roadmap slug to issue as label
uses: actions/github-script@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
@@ -20,7 +18,7 @@ jobs:
if (issue.labels.some(label => label.name === 'topic-change')) {
if (roadmapUrl) {
const roadmapSlug = new URL(roadmapUrl[0]).pathname.replace(/\//, '');
github.rest.issues.addLabels({
github.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
@@ -30,7 +28,7 @@ jobs:
// Close the issue if it has no roadmap URL
if (!roadmapUrl) {
github.rest.issues.update({
github.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,

View File

@@ -1,35 +1,35 @@
name: Refresh Roadmap Content JSON
name: Refreshes roadmap content JSON
on:
workflow_dispatch:
workflow_dispatch: # allow manual run
schedule:
- cron: '0 0 * * *'
- cron: '0 0 * * *' # every day at midnight
jobs:
refresh-content:
upgrade-deps:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm@v9
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
run_install: false
- name: Setup Node.js Version 20 (LTS)
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 18
cache: 'pnpm'
- name: Install Dependencies and Generate Content JSON
- name: Install dependencies and generate content JSON
run: |
pnpm install
npm run generate:roadmap-content-json
- name: Create PR
uses: peter-evans/create-pull-request@v7
uses: peter-evans/create-pull-request@v4
with:
delete-branch: false
branch: "chore/update-content-json"
@@ -37,16 +37,9 @@ jobs:
labels: |
dependencies
automated pr
reviewers: kamranahmedse
reviewers: kamranahmedse,arikchakma
commit-message: "chore: update roadmap content json"
title: "Updated Roadmap Content JSON - Automated"
title: "Update roadmap content json"
body: |
## Updated Roadmap Content JSON
> [!IMPORTANT]
> This PR Updates the Roadmap Content JSON files stored in the `public` directory.
>
> Commit: ${{ github.sha }}
> Workflow Path: ${{ github.workflow_ref }}
**Please Review the Changes and Merge the PR if everything is fine.**
Updates the roadmap content JSON files in the `public` folder.
Please review the changes and merge if everything looks good.

38
.github/workflows/update-deps.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: Update dependencies
on:
workflow_dispatch: # allow manual run
schedule:
- cron: '0 0 * * 0' # every sunday at midnight
jobs:
upgrade-deps:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: 18
- uses: pnpm/action-setup@v2.2.2
with:
version: 7.13.4
- name: Upgrade dependencies
run: |
pnpm install
npm run upgrade
pnpm install --lockfile-only
- name: Create PR
uses: peter-evans/create-pull-request@v4
with:
delete-branch: false
branch: "update-deps"
base: "master"
labels: |
dependencies
automated pr
reviewers: kamranahmedse
commit-message: "chore: update dependencies to latest"
title: "Upgrade dependencies to latest"
body: |
Updates all dependencies to latest versions.
Please review the changes and merge if everything looks good.

View File

@@ -1,51 +0,0 @@
name: Upgrade Dependencies
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * 0'
jobs:
upgrade-deps:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js Version 20 (LTS)
uses: actions/setup-node@v4
with:
node-version: 20
- name: Setup pnpm@v9
uses: pnpm/action-setup@v4
with:
version: 9
- name: Install & Upgrade Dependencies
run: |
pnpm install
npm run upgrade
pnpm install --lockfile-only
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
with:
delete-branch: false
branch: "update-deps"
base: "master"
labels: |
dependencies
automated pr
reviewers: kamranahmedse
commit-message: "chore: update dependencies to latest"
title: "Upgrade Dependencies To Latest - Automated"
body: |
## Updated all Dependencies to Latest Versions.
> [!IMPORTANT]
> This PR Upgrades the Dependencies to the Latest Their Versions.
>
> Commit: ${{ github.sha }}
> Workflow Path: ${{ github.workflow_ref }}
**Please Review the Changes and Merge the PR if everything is fine.**

View File

@@ -1,6 +1,6 @@
# Contribution
First of all, thank you for considering to contribute. Please look at the details below:
First of all thank you for considering to contribute. Please look at the details below:
- [New Roadmaps](#new-roadmaps)
- [Existing Roadmaps](#existing-roadmaps)
@@ -25,22 +25,22 @@ For the existing roadmaps, please follow the details listed for the nature of co
## Adding Projects
If you have a project idea that you think we should add to the roadmap, feel free to open an issue with as many details about the project as possible and the roadmap you think it should be added to.
If you have a project idea that you think we should add to the roadmap, feel free to open an issue with as much details about the project as possible and the roadmap you think it should be added to.
The detailed format for the issue should be as follows:
The detailed format for issue should be as follows:
```
## What is this project about?
(Add an introduction to the project.)
(Add introduction to the project)
## Skills this Project Covers
(Comma separated list of skills, e.g. Programming Knowledge, Database, etc.)
(Comma separated list of skills e.g. Programming Knowledge, Database,)
## Requirements
( Detailed list of requirements, i.e. input, output, hints to help build this, etc.)
( Detailed list of requirements, i.e. input, output, an hints to help build this etc)
```
Have a look at this project to get an idea of [what we are looking for](https://roadmap.sh/projects/github-user-activity).
@@ -67,7 +67,7 @@ Visit the following resources to learn more:
- [@type@Description of link](Link)
```
`@type@` must be one of the following and describe the type of content you are adding:
`@type@` must be one of the following and describes the type of content you are adding:
- `@official@`
- `@opensource@`
@@ -82,11 +82,11 @@ It's important to add a valid type, this will help us categorize the content and
- <p><strong>Please don't use the project for self-promotion!</strong><br />
We believe this project is a valuable asset to the developer community, and it includes numerous helpful resources. We kindly ask you to avoid submitting pull requests for the sole purpose of self-promotion. We appreciate contributions that genuinely add value, such as guides from maintainers of well-known frameworks, and will consider accepting these even if they're self authored. Thank you for your understanding and cooperation!
We believe this project is a valuable asset to the developer community and it includes numerous helpful resources. We kindly ask you to avoid submitting pull requests for the sole purpose of self-promotion. We appreciate contributions that genuinely add value, such as guides from maintainers of well-known frameworks, and will consider accepting these even if they're self authored. Thank you for your understanding and cooperation!
- <p><strong>Adding everything available out there is not the goal!</strong><br />
The roadmaps represent the skillset most valuable today, i.e., if you were to enter any of the listed fields today, what would you learn? There might be things that are of-course being used today, but prioritize the things that are most in demand today, e.g., agree that lots of people are using angular.js today, but you wouldn't want to learn that instead of React, Angular, or Vue. Use your critical thinking to filter out non-essential stuff. Give honest arguments for why the resource should be included.</p>
The roadmaps represent the skillset most valuable today, i.e., if you were to enter any of the listed fields today, what would you learn? There might be things that are of-course being used today but prioritize the things that are most in demand today, e.g., agreed that lots of people are using angular.js today but you wouldn't want to learn that instead of React, Angular, or Vue. Use your critical thinking to filter out non-essential stuff. Give honest arguments for why the resource should be included.</p>
- <p><strong>Do not add things you have not evaluated personally!</strong><br />
@@ -98,12 +98,12 @@ It's important to add a valid type, this will help us categorize the content and
- <p><strong>Write meaningful commit messages</strong><br >
Meaningful commit messages help speed up the review process as well as help other contributors gain a good overview of the repositories commit history without having to dive into every commit.
Meaningful commit messages help speed up the review process as well as help other contributors in gaining a good overview of the repositories commit history without having to dive into every commit.
</p>
- <p><strong>Look at the existing issues/pull requests before opening new ones</strong></p>
### Good vs. Not So Good Contributions
### Good vs Not So Good Contributions
<strong>Good</strong>
@@ -117,5 +117,5 @@ It's important to add a valid type, this will help us categorize the content and
- Adding whitespace that doesn't add to the readability of the content.
- Rewriting content in a way that doesn't add any value.
- Non-English content.
- PR's that don't follow our style guide, have no description, and a default title.
- PR's that don't follow our style guide, have no description and a default title.
- Links to your own blog articles.

377
package-lock.json generated
View File

@@ -8,8 +8,8 @@
"name": "roadmap.sh",
"version": "1.0.0",
"dependencies": {
"@astrojs/node": "^8.3.3",
"@astrojs/react": "^3.6.2",
"@astrojs/node": "^8.3.2",
"@astrojs/react": "^3.6.1",
"@astrojs/sitemap": "^3.1.6",
"@astrojs/tailwind": "^5.1.0",
"@fingerprintjs/fingerprintjs": "^4.4.3",
@@ -18,7 +18,7 @@
"@resvg/resvg-js": "^2.6.2",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"astro": "^4.14.6",
"astro": "^4.13.0",
"clsx": "^2.1.1",
"dayjs": "^1.11.12",
"dom-to-image": "^2.6.0",
@@ -132,9 +132,9 @@
}
},
"node_modules/@astrojs/node": {
"version": "8.3.3",
"resolved": "https://registry.npmjs.org/@astrojs/node/-/node-8.3.3.tgz",
"integrity": "sha512-idrKhnnPSi0ABV+PCQsRQqVNwpOvVDF/+fkwcIiE8sr9J8EMvW9g/oyAt8T4X2OBJ8FUzYPL8klfCdG7r0eB5g==",
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/@astrojs/node/-/node-8.3.2.tgz",
"integrity": "sha512-Upv0D+9b3RXp7XViQTtrijaDqihHWbVHLdJQ2sxtPOEtw2GDrVxuC6LmXIUew5YvJ9Ylmpst6KizVwO8d/K9/Q==",
"dependencies": {
"send": "^0.18.0",
"server-destroy": "^1.0.1"
@@ -263,11 +263,11 @@
}
},
"node_modules/@babel/generator": {
"version": "7.25.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.5.tgz",
"integrity": "sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w==",
"version": "7.25.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz",
"integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==",
"dependencies": {
"@babel/types": "^7.25.4",
"@babel/types": "^7.25.0",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^2.5.1"
@@ -402,11 +402,11 @@
}
},
"node_modules/@babel/parser": {
"version": "7.25.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.4.tgz",
"integrity": "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==",
"version": "7.25.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz",
"integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==",
"dependencies": {
"@babel/types": "^7.25.4"
"@babel/types": "^7.25.2"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -489,15 +489,15 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.25.4",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.4.tgz",
"integrity": "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==",
"version": "7.25.3",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz",
"integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==",
"dependencies": {
"@babel/code-frame": "^7.24.7",
"@babel/generator": "^7.25.4",
"@babel/parser": "^7.25.4",
"@babel/generator": "^7.25.0",
"@babel/parser": "^7.25.3",
"@babel/template": "^7.25.0",
"@babel/types": "^7.25.4",
"@babel/types": "^7.25.2",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -506,9 +506,9 @@
}
},
"node_modules/@babel/types": {
"version": "7.25.4",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.4.tgz",
"integrity": "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==",
"version": "7.25.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz",
"integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==",
"dependencies": {
"@babel/helper-string-parser": "^7.24.8",
"@babel/helper-validator-identifier": "^7.24.7",
@@ -2047,36 +2047,10 @@
"node": ">= 10"
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
"integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==",
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/pluginutils/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.1.tgz",
"integrity": "sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz",
"integrity": "sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==",
"cpu": [
"arm"
],
@@ -2086,9 +2060,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.1.tgz",
"integrity": "sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.1.tgz",
"integrity": "sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==",
"cpu": [
"arm64"
],
@@ -2098,9 +2072,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.1.tgz",
"integrity": "sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.1.tgz",
"integrity": "sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==",
"cpu": [
"arm64"
],
@@ -2110,9 +2084,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.1.tgz",
"integrity": "sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.1.tgz",
"integrity": "sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==",
"cpu": [
"x64"
],
@@ -2122,9 +2096,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.1.tgz",
"integrity": "sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.1.tgz",
"integrity": "sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==",
"cpu": [
"arm"
],
@@ -2134,9 +2108,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.1.tgz",
"integrity": "sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.1.tgz",
"integrity": "sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==",
"cpu": [
"arm"
],
@@ -2146,9 +2120,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.1.tgz",
"integrity": "sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.1.tgz",
"integrity": "sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==",
"cpu": [
"arm64"
],
@@ -2158,9 +2132,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.1.tgz",
"integrity": "sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.1.tgz",
"integrity": "sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==",
"cpu": [
"arm64"
],
@@ -2170,9 +2144,9 @@
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.1.tgz",
"integrity": "sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.1.tgz",
"integrity": "sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==",
"cpu": [
"ppc64"
],
@@ -2182,9 +2156,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.1.tgz",
"integrity": "sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.1.tgz",
"integrity": "sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==",
"cpu": [
"riscv64"
],
@@ -2194,9 +2168,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.1.tgz",
"integrity": "sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.1.tgz",
"integrity": "sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==",
"cpu": [
"s390x"
],
@@ -2206,9 +2180,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.1.tgz",
"integrity": "sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.1.tgz",
"integrity": "sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==",
"cpu": [
"x64"
],
@@ -2218,9 +2192,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.1.tgz",
"integrity": "sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.1.tgz",
"integrity": "sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==",
"cpu": [
"x64"
],
@@ -2230,9 +2204,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.1.tgz",
"integrity": "sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.1.tgz",
"integrity": "sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==",
"cpu": [
"arm64"
],
@@ -2242,9 +2216,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.1.tgz",
"integrity": "sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.1.tgz",
"integrity": "sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==",
"cpu": [
"ia32"
],
@@ -2254,9 +2228,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.1.tgz",
"integrity": "sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.1.tgz",
"integrity": "sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==",
"cpu": [
"x64"
],
@@ -2266,9 +2240,9 @@
]
},
"node_modules/@shikijs/core": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.14.1.tgz",
"integrity": "sha512-KyHIIpKNaT20FtFPFjCQB5WVSTpLR/n+jQXhWHWVUMm9MaOaG9BGOG0MSyt7yA4+Lm+4c9rTc03tt3nYzeYSfw==",
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.13.0.tgz",
"integrity": "sha512-Mj5NVfbAXcD1GnwOTSPl8hBn/T8UDpfFQTptp+p41n/CbUcJtOq98WaRD7Lz3hCglYotUTHUWtzu3JhK6XlkAA==",
"dependencies": {
"@types/hast": "^3.0.4"
}
@@ -2900,22 +2874,21 @@
}
},
"node_modules/astro": {
"version": "4.14.6",
"resolved": "https://registry.npmjs.org/astro/-/astro-4.14.6.tgz",
"integrity": "sha512-MIDyNhtu3L4uakHvlTprh21eQPehYOtZSuSLtd+r6xZcl3lB+mlBz/hs1W3iHEQAORyJnKArWSY/aVOBKUyflA==",
"version": "4.13.4",
"resolved": "https://registry.npmjs.org/astro/-/astro-4.13.4.tgz",
"integrity": "sha512-uoW961qyU5xxCiUzITVX8wYmdWbSH1zeog9UomoWC5uNpnIbH6WxOPv/qYu2m7W4r2PCxdRqfVXoYjZhFyGfTA==",
"dependencies": {
"@astrojs/compiler": "^2.10.3",
"@astrojs/compiler": "^2.10.2",
"@astrojs/internal-helpers": "0.4.1",
"@astrojs/markdown-remark": "5.2.0",
"@astrojs/telemetry": "3.1.0",
"@babel/core": "^7.25.2",
"@babel/generator": "^7.25.5",
"@babel/parser": "^7.25.4",
"@babel/generator": "^7.25.0",
"@babel/parser": "^7.25.3",
"@babel/plugin-transform-react-jsx": "^7.25.2",
"@babel/traverse": "^7.25.4",
"@babel/types": "^7.25.4",
"@babel/traverse": "^7.25.3",
"@babel/types": "^7.25.2",
"@oslojs/encoding": "^0.4.1",
"@rollup/pluginutils": "^5.1.0",
"@types/babel__core": "^7.20.5",
"@types/cookie": "^0.6.0",
"acorn": "^8.12.1",
@@ -2946,10 +2919,8 @@
"js-yaml": "^4.1.0",
"kleur": "^4.1.5",
"magic-string": "^0.30.11",
"micromatch": "^4.0.8",
"mrmime": "^2.0.0",
"neotraverse": "^0.6.18",
"ora": "^8.1.0",
"ora": "^8.0.1",
"p-limit": "^6.1.0",
"p-queue": "^8.0.1",
"path-to-regexp": "^6.2.2",
@@ -2957,20 +2928,18 @@
"prompts": "^2.4.2",
"rehype": "^13.0.1",
"semver": "^7.6.3",
"shiki": "^1.14.1",
"shiki": "^1.12.1",
"string-width": "^7.2.0",
"strip-ansi": "^7.1.0",
"tsconfck": "^3.1.1",
"unist-util-visit": "^5.0.0",
"vfile": "^6.0.3",
"vite": "^5.4.2",
"vfile": "^6.0.2",
"vite": "^5.4.0",
"vitefu": "^0.2.5",
"which-pm": "^3.0.0",
"xxhash-wasm": "^1.0.2",
"yargs-parser": "^21.1.1",
"zod": "^3.23.8",
"zod-to-json-schema": "^3.23.2",
"zod-to-ts": "^1.2.0"
"zod-to-json-schema": "^3.23.2"
},
"bin": {
"astro": "astro.js"
@@ -3353,14 +3322,14 @@
}
},
"node_modules/cli-cursor": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
"integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
"integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
"dependencies": {
"restore-cursor": "^5.0.0"
"restore-cursor": "^4.0.0"
},
"engines": {
"node": ">=18"
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -6075,9 +6044,9 @@
]
},
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
"integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
"dependencies": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
@@ -6129,17 +6098,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/mimic-function": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
"integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -6223,14 +6181,6 @@
"node": "^18.0.0 || >=20.0.0"
}
},
"node_modules/neotraverse": {
"version": "0.6.18",
"resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz",
"integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==",
"engines": {
"node": ">= 10"
}
},
"node_modules/nlcst-to-string": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz",
@@ -6438,18 +6388,18 @@
}
},
"node_modules/ora": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/ora/-/ora-8.1.0.tgz",
"integrity": "sha512-GQEkNkH/GHOhPFXcqZs3IDahXEQcQxsSjEkK4KvEEST4t7eNzoMjxTzef+EZ+JluDEV+Raoi3WQ2CflnRdSVnQ==",
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz",
"integrity": "sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==",
"dependencies": {
"chalk": "^5.3.0",
"cli-cursor": "^5.0.0",
"cli-cursor": "^4.0.0",
"cli-spinners": "^2.9.2",
"is-interactive": "^2.0.0",
"is-unicode-supported": "^2.0.0",
"log-symbols": "^6.0.0",
"stdin-discarder": "^0.2.2",
"string-width": "^7.2.0",
"stdin-discarder": "^0.2.1",
"string-width": "^7.0.0",
"strip-ansi": "^7.1.0"
},
"engines": {
@@ -7432,34 +7382,47 @@
}
},
"node_modules/restore-cursor": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz",
"integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
"integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
"dependencies": {
"onetime": "^7.0.0",
"signal-exit": "^4.1.0"
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
},
"engines": {
"node": ">=18"
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/restore-cursor/node_modules/mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"engines": {
"node": ">=6"
}
},
"node_modules/restore-cursor/node_modules/onetime": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
"integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"dependencies": {
"mimic-function": "^5.0.0"
"mimic-fn": "^2.1.0"
},
"engines": {
"node": ">=18"
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/restore-cursor/node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"node_modules/retext": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz",
@@ -7532,9 +7495,9 @@
"integrity": "sha512-IQejjIfr9RIvesNwp3SyhEq1DMQ2RdJfJhgsb1AyPuKXsfJgOG8F++Cz1p3SIcY0bnB57Q16Ke2VJLjiUVwI3Q=="
},
"node_modules/rollup": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.1.tgz",
"integrity": "sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.1.tgz",
"integrity": "sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==",
"dependencies": {
"@types/estree": "1.0.5"
},
@@ -7546,22 +7509,22 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.21.1",
"@rollup/rollup-android-arm64": "4.21.1",
"@rollup/rollup-darwin-arm64": "4.21.1",
"@rollup/rollup-darwin-x64": "4.21.1",
"@rollup/rollup-linux-arm-gnueabihf": "4.21.1",
"@rollup/rollup-linux-arm-musleabihf": "4.21.1",
"@rollup/rollup-linux-arm64-gnu": "4.21.1",
"@rollup/rollup-linux-arm64-musl": "4.21.1",
"@rollup/rollup-linux-powerpc64le-gnu": "4.21.1",
"@rollup/rollup-linux-riscv64-gnu": "4.21.1",
"@rollup/rollup-linux-s390x-gnu": "4.21.1",
"@rollup/rollup-linux-x64-gnu": "4.21.1",
"@rollup/rollup-linux-x64-musl": "4.21.1",
"@rollup/rollup-win32-arm64-msvc": "4.21.1",
"@rollup/rollup-win32-ia32-msvc": "4.21.1",
"@rollup/rollup-win32-x64-msvc": "4.21.1",
"@rollup/rollup-android-arm-eabi": "4.18.1",
"@rollup/rollup-android-arm64": "4.18.1",
"@rollup/rollup-darwin-arm64": "4.18.1",
"@rollup/rollup-darwin-x64": "4.18.1",
"@rollup/rollup-linux-arm-gnueabihf": "4.18.1",
"@rollup/rollup-linux-arm-musleabihf": "4.18.1",
"@rollup/rollup-linux-arm64-gnu": "4.18.1",
"@rollup/rollup-linux-arm64-musl": "4.18.1",
"@rollup/rollup-linux-powerpc64le-gnu": "4.18.1",
"@rollup/rollup-linux-riscv64-gnu": "4.18.1",
"@rollup/rollup-linux-s390x-gnu": "4.18.1",
"@rollup/rollup-linux-x64-gnu": "4.18.1",
"@rollup/rollup-linux-x64-musl": "4.18.1",
"@rollup/rollup-win32-arm64-msvc": "4.18.1",
"@rollup/rollup-win32-ia32-msvc": "4.18.1",
"@rollup/rollup-win32-x64-msvc": "4.18.1",
"fsevents": "~2.3.2"
}
},
@@ -7792,11 +7755,11 @@
}
},
"node_modules/shiki": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-1.14.1.tgz",
"integrity": "sha512-FujAN40NEejeXdzPt+3sZ3F2dx1U24BY2XTY01+MG8mbxCiA2XukXdcbyMyLAHJ/1AUUnQd1tZlvIjefWWEJeA==",
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-1.13.0.tgz",
"integrity": "sha512-e0dWfnONbEv6xl7FJy3XIhsVHQ/65XHDZl92+6H9+4xWjfdo7pmkqG7Kg47KWtDiEtzM5Z+oEfb4vtRvoZ/X9w==",
"dependencies": {
"@shikijs/core": "1.14.1",
"@shikijs/core": "1.13.0",
"@types/hast": "^3.0.4"
}
},
@@ -8792,19 +8755,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/typescript": {
"version": "5.5.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
"integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/uc.micro": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
@@ -9014,11 +8964,12 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/vfile": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
"integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.2.tgz",
"integrity": "sha512-zND7NlS8rJYb/sPqkb13ZvbbUoExdbi4w3SfRrMq6R3FvnLQmmfpajJNITuuYm6AZ5uao9vy4BAos3EXBPf2rg==",
"dependencies": {
"@types/unist": "^3.0.0",
"unist-util-stringify-position": "^4.0.0",
"vfile-message": "^4.0.0"
},
"funding": {
@@ -9053,13 +9004,13 @@
}
},
"node_modules/vite": {
"version": "5.4.2",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz",
"integrity": "sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==",
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.0.tgz",
"integrity": "sha512-5xokfMX0PIiwCMCMb9ZJcMyh5wbBun0zUzKib+L65vAZ8GY9ePZMXxFrHbr/Kyll2+LSCY7xtERPpxkBDKngwg==",
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.41",
"rollup": "^4.20.0"
"postcss": "^8.4.40",
"rollup": "^4.13.0"
},
"bin": {
"vite": "bin/vite.js"
@@ -9354,11 +9305,6 @@
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true
},
"node_modules/xxhash-wasm": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz",
"integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A=="
},
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
@@ -9415,15 +9361,6 @@
"zod": "^3.23.3"
}
},
"node_modules/zod-to-ts": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-1.2.0.tgz",
"integrity": "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==",
"peerDependencies": {
"typescript": "^4.9.4 || ^5.0.2",
"zod": "^3"
}
},
"node_modules/zustand": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.4.tgz",

View File

@@ -29,8 +29,8 @@
"test:e2e": "playwright test"
},
"dependencies": {
"@astrojs/node": "^8.3.3",
"@astrojs/react": "^3.6.2",
"@astrojs/node": "^8.3.2",
"@astrojs/react": "^3.6.1",
"@astrojs/sitemap": "^3.1.6",
"@astrojs/tailwind": "^5.1.0",
"@fingerprintjs/fingerprintjs": "^4.4.3",
@@ -39,7 +39,7 @@
"@resvg/resvg-js": "^2.6.2",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"astro": "^4.14.6",
"astro": "^4.13.0",
"clsx": "^2.1.1",
"dayjs": "^1.11.12",
"dom-to-image": "^2.6.0",

666
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -199,19 +199,8 @@
},
"3fFNMhQIuuh-NRzSXYpXO": {
"title": "Constraint",
"description": "Lets you create large, complex layouts with a flat view hierarchy—no nested view groups. It's similar to `RelativeLayout` in that all views are laid out according to relationships between sibling views and the parent layout, but it's more flexible than RelativeLayout and easier to use. Its available on xml and jetpack compose.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Android developers: ConstraintLayout in xml",
"url": "https://developer.android.com/develop/ui/views/layout/constraint-layout",
"type": "article"
},
{
"title": "Android developers: ContraintLayout in compose",
"url": "https://developer.android.com/develop/ui/compose/layouts/constraintlayout",
"type": "article"
}
]
"description": "",
"links": []
},
"xIvplWfe-uDr9iHjPT1Mx": {
"title": "RecycleView",
@@ -314,30 +303,13 @@
},
"EzLjX4iRT7AxkAOsJYnSU": {
"title": "ListView",
"description": "Displays a vertically-scrollable collection of views, where each view is positioned immediatelybelow the previous view in the list.\n\nFor a more modern, flexible, and performant approach to displaying lists, use `RecyclerView`.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Android developers: ListView",
"url": "https://developer.android.com/reference/android/widget/ListView",
"type": "article"
}
]
"description": "",
"links": []
},
"amTxz7mS98lkhOrNMJXG_": {
"title": "Drawer",
"description": "The **Navigation Drawer** in Android is a sliding menu from the left that simplifies navigation between important app links. It opens by sliding or via an icon in the `ActionBar`. Its an overlay panel that replaces a screen dedicated to displaying options.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Android developers: DrawerLayout",
"url": "https://developer.android.com/reference/androidx/drawerlayout/widget/DrawerLayout",
"type": "article"
},
{
"title": "Navigate Drawer Tutorial",
"url": "https://www.digitalocean.com/community/tutorials/android-navigation-drawer-example-tutorial",
"type": "article"
}
]
"description": "",
"links": []
},
"pEBpXv3Jf1AzBNHlvVrG8": {
"title": "Tabs",
@@ -352,19 +324,8 @@
},
"Xn1VQ-xOT67ZfJJTM4r1p": {
"title": "Animations",
"description": "`Animations` can add visual cues that notify users about what's going on in your app. They are especially useful when the UI changes state, such as when new content loads or new actions become available. Animations also add a polished look to your app, which gives it a higher quality look and feel.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Google developers: Animations",
"url": "https://developer.android.com/develop/ui/views/animations/overview",
"type": "article"
},
{
"title": "Google developers: Animations",
"url": "https://www.youtube.com/watch?v=N_x7SV3I3P0",
"type": "video"
}
]
"description": "",
"links": []
},
"60Vm-77rseUqpMiFvp-dA": {
"title": "Jetpack Compose",

View File

@@ -247,34 +247,8 @@
},
"19c7D-fWIJ3vYFT6h8ZfN": {
"title": "Communication",
"description": "Angular components can communicate with each other using `@Input()` and `@Output()` decorators. These decorators facilitate data exchange between parent and child components.\n\n* **@Input()**: This decorator allows a parent component to pass data to a child component, enabling the child to receive and use the data.\n* **@Output()**: This decorator allows a child component to emit events to a parent component, enabling the parent to respond to changes or actions within the child component.\n\nAdditionally, **model inputs** are a special type of input that enable two-way data binding. This means that changes in the child component can be propagated back to the parent component, ensuring synchronization between the two. Model inputs automatically create a corresponding output, typically named by appending “Change” to the inputs name, to facilitate this two-way communication.\n\nTo facilitate communication between unrelated components, its most effective to trigger events using `EventEmitter` and have the components listen for these events. This approach ensures a decoupled and flexible architecture, allowing components to interact seamlessly without direct dependencies.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Website - Inputs",
"url": "https://angular.dev/guide/components/inputs",
"type": "article"
},
{
"title": "Angular Official Website - Outputs",
"url": "https://angular.dev/guide/components/outputs",
"type": "article"
},
{
"title": "Angular Official Docs - Model Inputs",
"url": "https://angular.dev/guide/signals/model",
"type": "article"
},
{
"title": "Custom events with outputs",
"url": "https://angular.dev/guide/components/outputs",
"type": "article"
},
{
"title": "Non-Related Component Communication | Angular Component & Directives",
"url": "https://www.youtube.com/watch?v=aIkGXMJFTzM",
"type": "video"
}
]
"description": "",
"links": []
},
"TDyFjKrIZJnCjEZsojPNQ": {
"title": "Parent-Child Interaction",
@@ -357,34 +331,8 @@
},
"tC5ETtOuuUcybj1jI4CuG": {
"title": "Dynamic Components",
"description": "In addition to using a component directly in a template, you can also dynamically render components. There are two main ways to dynamically render a component: in a template with `NgComponentOutlet`, or in your TypeScript code with `ViewContainerRef`.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Programmatically rendering components",
"url": "https://angular.dev/guide/components/programmatic-rendering",
"type": "article"
},
{
"title": "New Input Binding for NgComponentOutlet",
"url": "https://medium.com/ngconf/new-input-binding-for-ngcomponentoutlet-cb18a86a739d",
"type": "article"
},
{
"title": "Render dynamic components in Angular using ViewContainerRef",
"url": "https://dev.to/railsstudent/render-dynamic-components-in-angular-using-viewcontainerref-160h",
"type": "article"
},
{
"title": "Dynamic Component in Angular (2024)",
"url": "https://www.youtube.com/watch?v=ncbftt3NWVo",
"type": "video"
},
{
"title": "Mastering ViewContainerRef for dynamic component loading in Angular17",
"url": "https://www.youtube.com/watch?v=Ra4PITCt8m0",
"type": "video"
}
]
"description": "",
"links": []
},
"b_kdNS9PDupcUftslkf9i": {
"title": "Modules",
@@ -658,6 +606,11 @@
}
]
},
"Wc2ybRw43uamEtno0FpDv": {
"title": "Template Ref Vars",
"description": "",
"links": []
},
"VsU6713jeIjAOEZnF6gWx": {
"title": "@Input & @Output",
"description": "`@Input()` and `@Output()` give a child component a way to communicate with its parent component. `@Input()` lets a parent component update data in the child component. Conversely, `@Output()` lets the child send data to a parent component.\n\nVisit the following resources to learn more:",
@@ -687,24 +640,8 @@
},
"VsC7UmE_AumsBP8fC6to1": {
"title": "Template Syntax",
"description": "In Angular, a _template_ is a chunk of HTML. Use special syntax within a template to build on many of Angular's features. Extend the HTML vocabulary of your applications with special Angular syntax in your templates. For example, Angular helps you get and set DOM (Document Object Model) values dynamically with features such as built-in template functions, variables, event listening, and data binding.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Template Syntax",
"url": "https://angular.dev/guide/templates",
"type": "article"
},
{
"title": "An Introduction to Angular Template Syntax",
"url": "https://angularstart.com/modules/basic-angular-concepts/3/",
"type": "article"
},
{
"title": "Craft Dynamic Templates with Angular's Template Syntax",
"url": "https://www.youtube.com/watch?v=uSnUTcf8adI",
"type": "video"
}
]
"description": "",
"links": []
},
"U1Zy2T-2ki9pDkXn9hn-I": {
"title": "@if",
@@ -740,19 +677,8 @@
},
"ys5untkSppGMFK-VsfuRt": {
"title": "@else if",
"description": "With the new control flow syntax, you gain `@else if` conditional blocks, something that is not possible with `@ngIf`. This addition makes the control flow syntax close to what we would write with just plain JavaScript.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - @if",
"url": "https://angular.dev/api/core/@if",
"type": "article"
},
{
"title": "Angular @if: Complete Guide",
"url": "https://blog.angular-university.io/angular-if/",
"type": "article"
}
]
"description": "",
"links": []
},
"2kYS9w1UzQFZ1zhf01m9L": {
"title": "@for",
@@ -767,51 +693,18 @@
},
"nZuim4Fjq6jYOXcRTAEay": {
"title": "@switch",
"description": "The `@switch` blocks displays content selected by one of the cases matching against the conditional expression. The value of the conditional expression is compared to the case expression using the `===` operator. `@switch` does not have fallthrough, so you do not need an equivalent to a break or return statement.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - @switch",
"url": "https://angular.dev/guide/templates/control-flow#switch-block---selection",
"type": "article"
},
{
"title": "Angular @switch: Complete Guide",
"url": "https://blog.angular-university.io/angular-switch/",
"type": "article"
}
]
"description": "",
"links": []
},
"cHC2MH50CbUSMRZV4QGJI": {
"title": "@case",
"description": "If no `@case` matches the `@switch` condition and there is no `@default` block, nothing is shown. Otherwise, the content inside the `@case` that matches the condition will be displayed.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - @switch",
"url": "https://angular.dev/guide/templates/control-flow#switch-block---selection",
"type": "article"
},
{
"title": "Angular @switch: Complete Guide",
"url": "https://blog.angular-university.io/angular-switch/",
"type": "article"
}
]
"description": "",
"links": []
},
"h4MMn0_qUN3YXEdMUJOyd": {
"title": "@default",
"description": "The `@default` clause is used to render a template when none of the `@case` blocks matches the value of the `@switch` conditional. `@default` is optional and can be omitted.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - @switch",
"url": "https://angular.dev/guide/templates/control-flow#switch-block---selection",
"type": "article"
},
{
"title": "Angular @switch: Complete Guide",
"url": "https://blog.angular-university.io/angular-switch/",
"type": "article"
}
]
"description": "",
"links": []
},
"AwOM0ucg6W7TohdUd7KWT": {
"title": "@let",
@@ -1081,7 +974,7 @@
},
"YF_sG292HqawIX0siWhrv": {
"title": "Router Events",
"description": "The Angular Router raises events when it navigates from one route to another route. It raises several events such as `NavigationStart`, `NavigationEnd`, `NavigationCancel`, `NavigationError`, `ResolveStart`, etc. You can listen to these events and find out when the state of the route changes. Some of the useful events are route change start (NavigationStart) and route change end (NavigationEnd).\n\nVisit the following resources to learn more:",
"description": "The Angular Router raises events when it navigates from one route to another route. It raises several events such as `NavigationStart`, `NavigationEnd`, `NavigationCancel`, `NavigationError`, `ResolveStart`, etc. You can listen to these events and find out when the state of the route changes. Some of the useful events are route change start (NavigationStart) and route change end (NavigationEnd).",
"links": [
{
"title": "Router reference - Router events",
@@ -1092,11 +985,6 @@
"title": "Router event - API",
"url": "https://angular.dev/api/router/RouterEvent",
"type": "article"
},
{
"title": "Router events in Angular",
"url": "https://medium.com/@gurunadhpukkalla/router-events-in-angular-3112a3968660",
"type": "article"
}
]
},
@@ -1217,34 +1105,8 @@
},
"XC_K1Wahl2ySqOXoym4YU": {
"title": "Typed Forms",
"description": "Since Angular 14, reactive forms are strictly typed by default. You don't have to define extra custom types or add a ton of type annotations to your form declarations to benefit from this extra type safety, as Angular will infer types from the default value of a form control. Non-typed forms are still supported. To use them, you must import the `Untyped` symbols from `@angular/forms`.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - @let",
"url": "https://angular.dev/api/core/@let",
"type": "article"
},
{
"title": "Angular Strictly Typed Forms (Complete Guide)",
"url": "https://blog.angular-university.io/angular-typed-forms/",
"type": "article"
},
{
"title": "Getting started with typed reactive forms in Angular",
"url": "https://www.youtube.com/watch?v=mT3UR0TdDnU",
"type": "video"
},
{
"title": "Angular TYPED Forms: Are You Using Them Correctly?",
"url": "https://www.youtube.com/watch?v=it2BZoIvBPc",
"type": "video"
},
{
"title": "Knowing this makes Angular typed forms WAY less awkward",
"url": "https://www.youtube.com/watch?v=xpRlijg6spo",
"type": "video"
}
]
"description": "",
"links": []
},
"uDx4lPavwsJFBMzdQ70CS": {
"title": "Template-driven Forms",
@@ -1401,29 +1263,8 @@
},
"lfp7PIjwITU5gBITQdirD": {
"title": "RxJS Basics",
"description": "Reactive Extensions for JavaScript, or RxJS, is a reactive library used to implement reactive programming to deal with async implementation, callbacks, and event-based programs.\n\nThe reactive paradigm can be used in many different languages through the use of reactive libraries. These libraries are downloaded APIs that provide functionalities for reactive tools like observers and operators. It can be used in your browser or with Node.js.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "RxJS Docs",
"url": "https://rxjs.dev/guide/overview",
"type": "article"
},
{
"title": "Learn RxJS",
"url": "https://www.learnrxjs.io/",
"type": "article"
},
{
"title": "RxJs and Observables for Beginners: A Beginner Friendly Introduction",
"url": "https://blog.angular-university.io/functional-reactive-programming-for-angular-2-developers-rxjs-and-observables/",
"type": "article"
},
{
"title": "Beginner's RxJS Tutorial: Dive Deep with RxJS Crash Course!",
"url": "https://www.youtube.com/watch?v=yJdh1_FbtjU",
"type": "video"
}
]
"description": "Reactive Extensions for JavaScript, or RxJS, is a reactive library used to implement reactive programming to deal with async implementation, callbacks, and event-based programs.\n\nThe reactive paradigm can be used in many different languages through the use of reactive libraries. These libraries are downloaded APIs that provide functionalities for reactive tools like observers and operators. It can be used in your browser or with Node.js.",
"links": []
},
"krXA6ua7E3m4IIpFkgQZe": {
"title": "Observable Pattern",
@@ -1518,13 +1359,8 @@
},
"kdMJHljMzGA3oRlh8Zvos": {
"title": "Transformation",
"description": "In RxJS, \"transformation\" refers to the process of modifying or manipulating the data emitted by an Observable. There are a variety of methods available in RxJS that can be used to transform the data emitted by an Observable, including:\n\n* **map**: applies a function to each item emitted by the Observable and emits the resulting value\n* **mergeMap**: applies a function to each item emitted by the Observable, and then merges the resulting Observables into a single Observable\n* **switchMap**: applies a function to each item emitted by the Observable, and then switches to the latest resulting Observable\n* **concatMap**: applies a function to each item emitted by the Observable, and then concatenates the resulting Observables into a single Observable\n* **exhaustMap**: applies a function to each item emitted by the Observable, but ignores subsequent emissions until the current Observable completes\n\nThese are just a few examples of the many methods available in RxJS for transforming the data emitted by an Observable. Each method has its own specific use case, and the best method to use will depend on the requirements of your application.\n\nVisit the following resources to learn more:",
"description": "In RxJS, \"transformation\" refers to the process of modifying or manipulating the data emitted by an Observable. There are a variety of methods available in RxJS that can be used to transform the data emitted by an Observable, including:\n\n* map: applies a function to each item emitted by the Observable and emits the resulting value\n* mergeMap: applies a function to each item emitted by the Observable, and then merges the resulting Observables into a single Observable\n* switchMap: applies a function to each item emitted by the Observable, and then switches to the latest resulting Observable\n* concatMap: applies a function to each item emitted by the Observable, and then concatenates the resulting Observables into a single Observable\n* exhaustMap: applies a function to each item emitted by the Observable, but ignores subsequent emissions until the current Observable completes\n\nThese are just a few examples of the many methods available in RxJS for transforming the data emitted by an Observable. Each method has its own specific use case, and the best method to use will depend on the requirements of your application.\n\nHere are the official documentation links for the RxJS transformation methods:\n\nYou can find more information and examples on these methods in the official RxJS documentation. Additionally, you can find more operators on [https://rxjs.dev/api/operators](https://rxjs.dev/api/operators) and you can also find more information on the library as a whole on [https://rxjs.dev/](https://rxjs.dev/)",
"links": [
{
"title": "RxJs Docs - Operators",
"url": "https://rxjs.dev/api/operators",
"type": "article"
},
{
"title": "map",
"url": "https://rxjs.dev/api/operators/map",
@@ -1783,7 +1619,7 @@
},
"m4WBnx_9h01Jl6Q1sxi4Y": {
"title": "Zones",
"description": "Zone.js is a signaling mechanism that Angular uses to detect when an application state might have changed. It captures asynchronous operations like setTimeout, network requests, and event listeners. Angular schedules change detection based on signals from Zone.js.\n\nVisit the following resources to learn more:",
"description": "Zone.js is a signaling mechanism that Angular uses to detect when an application state might have changed. It captures asynchronous operations like setTimeout, network requests, and event listeners. Angular schedules change detection based on signals from Zone.js.",
"links": [
{
"title": "Resolving zone pollution",
@@ -1799,11 +1635,6 @@
"title": "NgZone - API",
"url": "https://angular.dev/api/core/NgZone",
"type": "article"
},
{
"title": "WTF is \"Zone.js\" and is it making your app slow?",
"url": "https://www.youtube.com/watch?v=lmrf_gPIOZU",
"type": "video"
}
]
},
@@ -1845,29 +1676,8 @@
},
"EbJib-XfZFF9bpCtL3aBs": {
"title": "Developer Tools",
"description": "Angular offers a suite of powerful developer tools designed to streamline and enhance the development process. These include the Angular CLI for efficient project setup and management, the Angular DevTools extension for advanced debugging and profiling, and the Angular Language Service for improved code editing and completion. Leveraging these tools will significantly improve your ability to write high-quality Angular code.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "VS Code NG Language Service",
"url": "https://github.com/angular/vscode-ng-language-service",
"type": "opensource"
},
{
"title": "Angular Official Docs - devtools",
"url": "https://angular.dev/tools/devtools",
"type": "article"
},
{
"title": "Angular Official Docs - CLI",
"url": "https://angular.dev/tools/cli",
"type": "article"
},
{
"title": "Language Service Docs",
"url": "https://angular.dev/tools/language-service",
"type": "article"
}
]
"description": "",
"links": []
},
"4YSk6I63Ew--zoXC3xmrC": {
"title": "Angular CLI",
@@ -1897,106 +1707,18 @@
},
"FVH0lnbIZ2m5EfF2EJ2DW": {
"title": "Local Setup",
"description": "To install Angular CLI on your local system, you need to install `Node.js`. Angular requires an active LTS or maintenance LTS version of Node. Angular CLI uses Node and its associated package manager, npm, to install and run JavaScript tools outside the browser. Once you have Node installed, you can run `npm install -g @angular/cli` to install the Angular CLI.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Local set-up",
"url": "https://angular.dev/tools/cli/setup-local",
"type": "article"
},
{
"title": "Angular Official Docs - Version compatibility guide",
"url": "https://angular.dev/reference/versions",
"type": "article"
},
{
"title": "How To Install Angular CLI In Windows 10 | In Under 2 Minutes!",
"url": "https://www.youtube.com/watch?v=vjgACKkPENg",
"type": "video"
},
{
"title": "How to Install Multiple Versions of Angular in Your Development Environment",
"url": "https://www.youtube.com/watch?v=LYNG3kcKRQ8",
"type": "video"
}
]
"description": "",
"links": []
},
"1fVi9AK6aLjt5QgAFbnGX": {
"title": "Deployment",
"description": "The Angular CLI command `ng deploy` executes the deploy CLI builder associated with your project. A number of third-party builders implement deployment capabilities to different platforms. You can add any of them to your project with `ng add`.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "NGX AWS Deploy",
"url": "https://github.com/Jefiozie/ngx-aws-deploy",
"type": "opensource"
},
{
"title": "Angular CLI GitHub Pages",
"url": "https://github.com/angular-schule/angular-cli-ghpages",
"type": "opensource"
},
{
"title": "Angular Official Docs - Deployment",
"url": "https://angular.dev/tools/cli/deployment",
"type": "article"
},
{
"title": "Firebase Hosting",
"url": "https://firebase.google.com/docs/hosting",
"type": "article"
},
{
"title": "Vercel: Angular Solutions",
"url": "https://vercel.com/solutions/angular",
"type": "article"
},
{
"title": "Netlify",
"url": "https://docs.netlify.com/frameworks/angular/",
"type": "article"
},
{
"title": "Cloudflare Pages",
"url": "https://developers.cloudflare.com/pages/framework-guides/deploy-an-angular-site/#create-a-new-project-using-the-create-cloudflare-cli-c3",
"type": "article"
},
{
"title": "AWS Amplify",
"url": "https://docs.amplify.aws/angular/",
"type": "article"
}
]
"description": "",
"links": []
},
"yhNGhduk__ow8VTLc6inZ": {
"title": "End-to-End Testing",
"description": "End-to-end or (E2E) testing is a form of testing used to assert your entire application works as expected from start to finish or \"end-to-end\". E2E testing differs from unit testing in that it is completely decoupled from the underlying implementation details of your code. It is typically used to validate an application in a way that mimics the way a user would interact with it. The `ng e2e` command will first check your project for the \"e2e\" target. If it can't locate it, the CLI will then prompt you which e2e package you would like to use and walk you through the setup.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - End to End Testing",
"url": "https://angular.dev/tools/cli/end-to-end",
"type": "article"
},
{
"title": "Cypress Official Docs - Your First Test with Cypress",
"url": "https://docs.cypress.io/guides/end-to-end-testing/writing-your-first-end-to-end-test",
"type": "article"
},
{
"title": "Nightwatch Official Docs - Writing Tests: Introduction",
"url": "https://nightwatchjs.org/guide/writing-tests/introduction.html",
"type": "article"
},
{
"title": "Webdriver Official Docs - Getting Started",
"url": "https://webdriver.io/docs/gettingstarted/",
"type": "article"
},
{
"title": "Puppeteer Angular Schematic",
"url": "https://pptr.dev/guides/ng-schematics/#getting-started",
"type": "article"
}
]
"description": "",
"links": []
},
"Uvr0pRk_fOzwRwqn0dQ6N": {
"title": "Schematics",
@@ -2016,40 +1738,13 @@
},
"Ax-s_xw3FO3Ocv-AnLbQD": {
"title": "Build Environments",
"description": "You can define different named build configurations for your project, such as `development` and `production`, with different defaults. Each named configuration can have defaults for any of the options that apply to the various builder targets, such as `build`, `serve`, and `test`. The Angular CLI can replace files for each environment if you pass a `--configuration` flag with the named configuration when running a CLI command.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Build environments",
"url": "https://angular.dev/tools/cli/environments#using-environment-specific-variables-in-your-app",
"type": "article"
},
{
"title": "Building an Angular application in various environments using Angular CLI and server",
"url": "https://medium.com/yavar/building-an-angular-application-in-various-environments-using-angular-cli-and-server-18f94067154b",
"type": "article"
}
]
"description": "",
"links": []
},
"TeWEy9I-hU6SH02Sy2S2S": {
"title": "CLI Builders",
"description": "A number of Angular CLI commands run a complex process on your code, such as building, testing, or serving your application. The commands use an internal tool called `Architect` to run CLI builders, which invoke another tool (bundler, test runner, server) to accomplish the desired task. Custom builders can perform an entirely new task or to change which third-party tool is used by an existing command.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Builders",
"url": "https://github.com/just-jeb/angular-builders",
"type": "opensource"
},
{
"title": "Angular Official Docs - CLI Builders",
"url": "https://angular.dev/tools/cli/cli-builder",
"type": "article"
},
{
"title": "Angular Builders Creating Custom Builder from Scratch",
"url": "https://www.youtube.com/watch?v=QbDkDLnXAZE",
"type": "video"
}
]
"description": "",
"links": []
},
"MwtM1UAIfj4FJ-Y4CKDsP": {
"title": "AoT Compilation",
@@ -2127,40 +1822,13 @@
},
"YHV5oFwLwphXf1wJTDZuG": {
"title": "Using Libraries",
"description": "Libraries are published as `npm packages`, usually together with schematics that integrate them with the Angular CLI. To integrate reusable library code into an application, you need to install the package and import the provided functionality in the location you use it. For most published Angular libraries, use the `ng add <lib_name>` Angular CLI command. A published library typically provides a `README` file or other documentation on how to add that library to your application. A library is able to be updated by the publisher, and also has individual dependencies which need to be kept current. To check for updates to your installed libraries, use the `ng update` Angular CLI command.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Using Libraries",
"url": "https://angular.dev/tools/libraries/using-libraries",
"type": "article"
},
{
"title": "npm",
"url": "https://www.npmjs.com/",
"type": "article"
}
]
"description": "",
"links": []
},
"A1mYMg7cbcj6p_VkDf-Tz": {
"title": "Creating Libraries",
"description": "If you have developed features that are suitable for reuse, you can create your own libraries. These libraries can be used locally in your workspace, or you can publish them as npm packages to share with other projects or other Angular developers. Putting code into a separate library is more complex than simply putting everything in one application. It requires more of an investment in time and thought for managing, maintaining, and updating the library. This complexity can pay off when the library is being used in multiple applications.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "NG Packagr",
"url": "https://github.com/ng-packagr/ng-packagr",
"type": "opensource"
},
{
"title": "Angular Official Docs - Creating Libraries",
"url": "https://angular.dev/tools/libraries/creating-libraries",
"type": "article"
},
{
"title": "Angular Official Docs - File Structure: Library project files",
"url": "https://angular.dev/reference/configs/file-structure#library-project-files",
"type": "article"
}
]
"description": "",
"links": []
},
"jfHaS8TqE4tcAo59K8Nkn": {
"title": "SSR",
@@ -2185,24 +1853,8 @@
},
"b-0yQ74zHtAxI9aRLBohc": {
"title": "SSG",
"description": "SSG (Static Site Generator) helps in building the HTML full website during the process of building and serving that HTML page. This method helps to generate the HTML website on the client side before it's served on the server side. Therefore, whenever a user requests a HTML page, the HTML page will be rendered, and secondly, the Angular app will be rendered. The SSG can be used only if your website is static or its content doesn't change frequently.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Air with Alyssa Nicoll - SSR, SSG, ISR, & SOS",
"url": "https://www.youtube.com/watch?v=b0pUU7RJbBQ",
"type": "podcast"
},
{
"title": "Angular Official Docs - Prerendering (SSG)",
"url": "https://angular.dev/guide/prerendering",
"type": "article"
},
{
"title": "Angular 16 Pre Rendering Static Pages - Static Site Generation SSG",
"url": "https://www.youtube.com/watch?v=vmOWJvm3apA",
"type": "video"
}
]
"description": "SSG (Static Site Generator), helps in building the HTML full website, during the process of building and serving that HTML Page. This method helps to generate the HTML website on the client side before its being served on the server side. Therefore, whenever a user requests a HTML Page, firstly HTML page will be rendered and secondly, the angular app will be rendered. The SSG can be used only if your website is static (or) it's content doesn't changes frequently.",
"links": []
},
"kauQofxCmpktXPcnzid17": {
"title": "AnalogJS",
@@ -2312,66 +1964,18 @@
},
"xH3RHPhsaqD9zIMms5OmX": {
"title": "HTTP Vulnerabilities",
"description": "Angular has built-in support to help prevent two common HTTP vulnerabilities, cross-site request forgery (CSRF or XSRF) and cross-site script inclusion (XSSI). Both of these must be mitigated primarily on the server side, but Angular provides helpers to make integration on the client side easier.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Security",
"url": "https://angular.dev/best-practices/security",
"type": "article"
},
{
"title": "Angular | HackTricks",
"url": "https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/angular",
"type": "article"
}
]
"description": "",
"links": []
},
"Z1DZBbFI4oU6-KQg3wqMm": {
"title": "Cross-site Request Forgery",
"description": "Cross-site request forgery, also known as one-click attack or session riding and abbreviated as CSRF or XSRF, is a type of malicious exploit of a website or web application where unauthorized commands are submitted from a user that the web application trusts. There are many ways in which a malicious website can transmit such commands; specially-crafted image tags, hidden forms, and JavaScript fetch or XMLHttpRequests, for example, can all work without the user's interaction or knowledge. Unlike cross-site scripting (XSS), which exploits the trust a user has for a particular site, CSRF exploits the trust that a site has in a user's browser. In a CSRF attack, an innocent end user is tricked by an attacker into submitting a web request that they did not intend. This may cause actions to be performed on the website that can include inadvertent client or server data leakage, change of session state, or manipulation of an end user's account. Angular provides built-in protection against CSRF attacks through the `HttpClientXsrfModule` module. This module automatically adds a token to outgoing requests and validates it on the server side.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Cross Site Request Forgery",
"url": "https://angular.dev/best-practices/security#cross-site-request-forgery",
"type": "article"
},
{
"title": "HttpClientXsrfModule",
"url": "https://angular.dev/api/common/http/HttpClientXsrfModule",
"type": "article"
},
{
"title": "Configure the CSRF Protection With Spring Security 6 and Angular",
"url": "https://www.youtube.com/watch?v=tgjLsEmxcuY",
"type": "video"
},
{
"title": "Angular security - CSRF prevention using Double Submit Cookie",
"url": "https://www.youtube.com/watch?v=lZfF4MOTeNM",
"type": "video"
}
]
"description": "",
"links": []
},
"m2aw8vb4rz4IjshpoMyNx": {
"title": "HttpClient CSRF",
"description": "HttpClient includes a built-in mechanism to prevent XSRF attacks. When making HTTP requests, an interceptor reads a token from a cookie (default name: XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only code running on your domain can read this cookie, the backend can verify that the HTTP request originates from your client application and not from an attacker.\n\nHowever, HttpClient only handles the client-side aspect of XSRF protection. Your backend service must be configured to set the cookie for your page and verify that the header is present on all relevant requests. Without this backend configuration, Angulars default XSRF protection will not be effective.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Security",
"url": "https://angular.dev/best-practices/security#httpclient-xsrf-csrf-security",
"type": "article"
},
{
"title": "How can you protect Angular Web app from cross site request forgery?",
"url": "https://www.linkedin.com/advice/3/how-can-you-protect-angular-web-app-from-cross-site-pyqwc",
"type": "article"
},
{
"title": "Cross Site Request Forgery: XSRF protection in Angular",
"url": "https://borstch.com/blog/development/cross-site-request-forgery-xsrf-protection-in-angular",
"type": "article"
}
]
"description": "",
"links": []
},
"ni00edsphJd7uBLCn7-Vw": {
"title": "XSRF protection",
@@ -2380,24 +1984,8 @@
},
"zd7YJGlcMFNFbsKUiW_XC": {
"title": "Cross-site Script Inclusion",
"description": "Cross-site script inclusion, also known as JSON vulnerability, can allow an attacker's website to read data from a JSON API. The attack works on older browsers by overriding built-in JavaScript object constructors, and then including an API URL using a `<script>` tag. Angular's HttpClient library recognizes this convention and automatically strips the string \")\\]}',\\\\n\" from all responses before further parsing.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Cross Site Script Inclusion",
"url": "https://angular.dev/best-practices/security#cross-site-script-inclusion-xssi",
"type": "article"
},
{
"title": "XSSI Cross Site Script Inclusion",
"url": "https://book.hacktricks.xyz/pentesting-web/xssi-cross-site-script-inclusion",
"type": "article"
},
{
"title": "Testing for Cross Site Script Inclusion",
"url": "https://owasp.org/www-project-web-security-testing-guide/v41/4-Web_Application_Security_Testing/11-Client_Side_Testing/13-Testing_for_Cross_Site_Script_Inclusion",
"type": "article"
}
]
"description": "",
"links": []
},
"VNG9DdXlS6R1OJ6Lrn4Lt": {
"title": "Accessibility",
@@ -2565,118 +2153,28 @@
},
"pRSR5PEbkJXAJ1LPyK-EE": {
"title": "Zone Pollution",
"description": "`Zone.js` is a signaling mechanism that Angular uses to detect when an application state might have changed. In some cases, scheduled tasks or microtasks dont make any changes in the data model, which makes running change detection unnecessary. Common examples are `requestAnimationFrame`, `setTimeout` and `setInterval`. You can identify change detection with Angular DevTools, and you can run code outside the Angular zone to avoid unnecessary change detection calls.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Zone Pollution",
"url": "https://angular.dev/best-practices/zone-pollution",
"type": "article"
},
{
"title": "Angular Official Docs - DevTools",
"url": "https://angular.dev/tools/devtools",
"type": "article"
},
{
"title": "NgZone in Angular - Improve Performance by Running Code Outside Angular",
"url": "https://www.youtube.com/watch?v=7duYY9IFIuw",
"type": "video"
},
{
"title": "4 Runtime Performance Optimizations",
"url": "https://www.youtube.com/watch?v=f8sA-i6gkGQ",
"type": "video"
}
]
"description": "",
"links": []
},
"yxUtSBzJPRcS-IuPsyp-W": {
"title": "Slow Computations",
"description": "On every change detection cycle, Angular synchronously evaluates all template expressions in components based on their detection strategy and executes the `ngDoCheck`, `ngAfterContentChecked`, `ngAfterViewChecked`, and `ngOnChanges` lifecycle hooks. To remove slow computations, you can optimize algorithms, cache data with pure pipes or memoization, and limit lifecycle hook usage.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Slow Computations",
"url": "https://angular.dev/best-practices/slow-computations",
"type": "article"
},
{
"title": "Angular Performance Optimization",
"url": "https://davembush.medium.com/angular-performance-optimization-5ec630d2b8f1",
"type": "article"
}
]
"description": "",
"links": []
},
"NY_MfBNgNmloiRGcIvfJ1": {
"title": "Hydration",
"description": "Hydration is the process that restores the server-side rendered application on the client. This includes things like reusing the server rendered DOM structures, persisting the application state, transferring application data that was retrieved already by the server, and other processes. Hydration can be enabled for server-side rendered (SSR) applications only. You can enable hydration manually by visiting your main application component or module and importing `provideClientHydration` from `@angular/platform-browser`.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Hydration",
"url": "https://angular.dev/guide/hydration",
"type": "article"
},
{
"title": "Angular Official Docs - provideClientHydration",
"url": "https://angular.dev/api/platform-browser/provideClientHydration",
"type": "article"
},
{
"title": "Angular Hydration",
"url": "https://www.bacancytechnology.com/blog/angular-hydration",
"type": "article"
},
{
"title": "Angular SSR Deep Dive (With Client HYDRATION)",
"url": "https://www.youtube.com/watch?v=U1MP4uCuUVI",
"type": "video"
}
]
"description": "",
"links": []
},
"lLa-OnHV6GzkNFZu29BIT": {
"title": "Testing",
"description": "In any software development process, testing the application plays a vital role. If bugs and crashes are not figured out and solved they can defame the development company as well as hurt the clients too. But, Angulars architecture comes with built-in testability features. As soon as you create a new project with Angular CLI, two essential testing tools are installed. They are: Jasmine and Karma. Jasmine is the testing library which structures individual tests into specifications (“specs”) and suites. And Karma is the test runner, which enables the different browsers to run the tests mentioned by Jasmine and the browsers will finally report the test results back.\n\nYou can also unit test an Angular application with other testing libraries and test runners. Each library and runner has its own distinctive installation procedures, configuration, and syntax.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Testing",
"url": "https://angular.dev/guide/testing",
"type": "article"
},
{
"title": "Jasmine Official Docs",
"url": "https://jasmine.github.io/",
"type": "article"
},
{
"title": "Karma Official Docs",
"url": "https://karma-runner.github.io/latest/index.html",
"type": "article"
},
{
"title": "Testing Angular - A Guide to Robust Angular Applications",
"url": "https://testing-angular.com/",
"type": "article"
},
{
"title": "Introduction | Angular Unit Testing Made Easy: A Comprehensive Introduction",
"url": "https://www.youtube.com/watch?v=emnwsVy8wRs",
"type": "video"
}
]
"description": "In any software development process, Testing the application plays a vital role. If Bugs and crashes are not figured out and solved they can defame the development company as well as hurt the clients too. But, Angulars architecture comes with built-in testability features. As soon as you create a new project with Angular CLI, two essential testing tools are installed.They are: Jasmine and Karma. Jasmine is the testing library which structures individual tests into specifications (“specs”) and suites. And Karma is the test runner, which enables the different browsers to run the tests mentioned by Jasmine and the browsers will finally report the test results back.",
"links": []
},
"HU1eTYB321C93qh_U7ioF": {
"title": "Testing Services",
"description": "To ensure your services function as expected, you can write dedicated tests for them. Services are typically the easiest files to unit test. You can instantiate the service within a `beforeEach` block, invoke its methods, and assert the results.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Testing Services",
"url": "https://angular.dev/guide/testing/services",
"type": "article"
},
{
"title": "Step by Step implementation of the Calculator Service with Jasmine Specification",
"url": "https://www.youtube.com/watch?v=yoJDYEq8vSs",
"type": "video"
}
]
"description": "",
"links": []
},
"rH13NBFG02hnn5eABSNCY": {
"title": "Testing Pipes",
@@ -2701,28 +2199,12 @@
},
"4xt0m5jkUqB4Z-krcFBuL": {
"title": "Testing Requests",
"description": "As for any external dependency, you must mock the HTTP backend so your tests can simulate interaction with a remote server. The `@angular/common/http/testing` library provides tools to capture requests made by the application, make assertions about them, and mock the responses to emulate your backend's behavior.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Testing Requests",
"url": "https://angular.dev/guide/http/testing",
"type": "article"
},
{
"title": "Import Http Client Testing Module and make Test call with the HttpClient",
"url": "https://www.youtube.com/watch?v=Sgy_RRXC9As",
"type": "video"
},
{
"title": "HTTP | Angular Unit Testing Made Easy: Comprehensive Guide to HTTP Testing",
"url": "https://www.youtube.com/watch?v=7rlwryYhGzs",
"type": "video"
}
]
"description": "",
"links": []
},
"TGRZBizDy83JKg_MhnRdX": {
"title": "Services with Dependencies",
"description": "When you add a dependency to your service, you must also include it in your tests. For isolated tests, pass an instance of the injectable dependency class into the services constructor. Using the `inject` function can add complexity. Injecting the real service is often impractical because dependent services can be difficult to create and control. Instead, mock the dependency, use a dummy value, or create a spy on the relevant service method. By using the TestBed testing utility, you can let Angulars dependency injection handle service creation and manage constructor argument order.\n\nVisit the following resources to learn more:",
"description": "In an Angular application, Services are responsible for fetching, storing and processing data. Services are singletons, meaning there is only one instance of a Service during runtime. They are fit for central data storage, HTTP and WebSocket communication as well as data validation.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Website",
@@ -2735,19 +2217,9 @@
"type": "article"
},
{
"title": "Testing the Service which has another service injected through Dependency Injection",
"url": "https://www.youtube.com/watch?v=ACb8wqwgOV4",
"type": "video"
},
{
"title": "Testing Services which has HttpClient as dependency by using Jasmine Spy",
"url": "https://www.youtube.com/watch?v=15othucRXcI",
"type": "video"
},
{
"title": "Angular Unit Tests with the inject() function",
"url": "https://www.youtube.com/watch?v=Tvsa4OMUGXs",
"type": "video"
"title": "Explore top posts about Testing",
"url": "https://app.daily.dev/tags/testing?ref=roadmapsh",
"type": "article"
}
]
},
@@ -2790,29 +2262,8 @@
},
"f5v74Uw54LsB4FgdN6eCd": {
"title": "Debugging Tests",
"description": "If your tests aren't working as you expect them to, you can inspect and debug them in the browser. Be sure to set breakpoints to track your application's execution.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Debugging tests",
"url": "https://angular.dev/guide/testing/debugging",
"type": "article"
},
{
"title": "Angular Official Docs - Devtools",
"url": "https://angular.dev/tools/devtools",
"type": "article"
},
{
"title": "Debug Like a Pro: Essential Breakpoint Techniques in Angular",
"url": "https://www.youtube.com/watch?v=Be9Q1cchurQ",
"type": "video"
},
{
"title": "Debug Angular 17 Code in VS Code with Break Points and Extensions",
"url": "https://www.youtube.com/watch?v=r50UXhT9hc0",
"type": "video"
}
]
"description": "",
"links": []
},
"0dYWO_Zvh9J5_6cRjRjvI": {
"title": "Component Templates",
@@ -2879,87 +2330,23 @@
},
"W8OwpEw00xn0GxidlJjdc": {
"title": "Localize Package",
"description": "To take advantage of the localization features of Angular, use the Angular CLI to add the `@angular/localize` package to your project. If `@angular/localize` is not installed and you try to build a localized version of your project (for example, while using the i18n attributes in templates), the Angular CLI will generate an error, which would contain the steps that you can take to enable i18n for your project.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Add the localize package",
"url": "https://angular.dev/guide/i18n/add-package",
"type": "article"
},
{
"title": "Learn to Internationalize Your Angular Apps with @angular/localize",
"url": "https://www.youtube.com/watch?v=5h7HPY1OMfU",
"type": "video"
},
{
"title": "Multi-Language Support in Angular: A Guide to Localization and Internationalization",
"url": "https://www.youtube.com/watch?v=ouI21AyJ9tE",
"type": "video"
}
]
"description": "",
"links": []
},
"dVKl3Z2Rnf6IB064v19Mi": {
"title": "Locales by ID",
"description": "Angular uses the Unicode locale identifier (Unicode locale ID) to find the correct locale data for internationalization of text strings. A locale ID specifies the language, country, and an optional code for further variants or subdivisions. A locale ID consists of the language identifier, a hyphen (-) character, and the locale extension. By default, Angular uses `en-US` as the source locale of your project.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular locales",
"url": "https://github.com/angular/angular/tree/main/packages/common/locales",
"type": "opensource"
},
{
"title": "Angular Official Docs - Refer to locales by ID",
"url": "https://angular.dev/guide/i18n/locale-id",
"type": "article"
},
{
"title": "Codes arranged alphabetically by alpha-3/ISO 639-2 Code",
"url": "https://www.loc.gov/standards/iso639-2/php/code_list.php",
"type": "article"
},
{
"title": "Unicode CLDR Specifications",
"url": "https://cldr.unicode.org/index/cldr-spec",
"type": "article"
}
]
"description": "",
"links": []
},
"jL5amGV1BAX_V5cyTIH7d": {
"title": "Translation Files",
"description": "After you prepare a component for translation, use the `extract-i18n` Angular CLI command to extract the marked text in the component into a source language file. The marked text includes text marked with `i18n`, attributes marked with `i18n`\\-attribute, and text tagged with `$localize`. The `extract-i18n` command creates a source language file named `messages.xlf` in the root directory of your project. If you have multiple language files, add the locale to the file name, like `messages.{locale}.xlf`.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Translation Files",
"url": "https://angular.dev/guide/i18n/translation-files",
"type": "article"
},
{
"title": "Angular Official Docs - Extract i18n",
"url": "https://angular.dev/cli/extract-i18n",
"type": "article"
},
{
"title": "Angular i18n: internationalization & localization with examples",
"url": "https://lokalise.com/blog/angular-i18n/",
"type": "article"
}
]
"description": "",
"links": []
},
"9ISvaaJ815_cr_KW9vQhT": {
"title": "Multiple Locales",
"description": "To deploy an Angular application with multiple locales, follow these steps:\n\n1. Place different versions of your app in locale-specific directories\n2. Use the HTML `<base>` tag with the `href` attribute to set the base URL for relative links.\n3. Deploy each language version in a different subdirectory. Redirect users to their preferred language based on the `Accept-Language` HTTP header.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Angular Official Docs - Deploy Multiple Locales",
"url": "https://angular.dev/guide/i18n/deploy",
"type": "article"
},
{
"title": "How Make Multi-Language Angular Websites - Full Guidance On Angular Localization",
"url": "https://www.youtube.com/watch?v=vSwYuyH4kMA",
"type": "video"
}
]
"description": "",
"links": []
},
"rYJq59Q0YdfK6n3x740Em": {
"title": "Animation",

View File

@@ -191,21 +191,41 @@
},
"8-lO-v6jCYYoklEJXULxN": {
"title": "JavaScript",
"description": "JavaScript allows you to add interactivity to your pages. Common examples that you may have seen on the websites are sliders, click interactions, popups and so on.\n\nVisit the following resources to learn more:",
"description": "Apart from being used in the browser, JavaScript is also used in backend e.g. using [Node.js](https://nodejs.org/) or [Deno](https://deno.land/) for writing server-side code in JavaScript.\n\nIf you pick up JavaScript for the Backend, my personal recommendation would be to learn [JavaScript](/javascript) and then go with [Node.js](/nodejs) as it is the most popular and widely used option. Also, I would recommend learning TypeScript later on as you continue with your backend development Journey; it's a superset of JavaScript and is used in many projects.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "You Dont Know JS Yet (book series) ",
"url": "https://github.com/getify/You-Dont-Know-JS",
"type": "opensource"
},
{
"title": "Visit Dedicated JavaScript Roadmap",
"url": "/javascript",
"type": "article"
},
{
"title": "W3Schools JavaScript Tutorial",
"url": "https://www.w3schools.com/js/",
"type": "article"
},
{
"title": "The Modern JavaScript Tutorial",
"url": "https://javascript.info/",
"type": "article"
},
{
"title": "Build 30 Javascript projects in 30 days",
"url": "https://javascript30.com/",
"title": "Eloquent Javascript - Book",
"url": "https://eloquentjavascript.net/",
"type": "article"
},
{
"title": "Visit Dedicated Node.js Roadmap",
"url": "/nodejs",
"type": "article"
},
{
"title": "Official JavaScript Documentation",
"url": "https://www.javascript.com/",
"type": "article"
},
{
@@ -215,7 +235,17 @@
},
{
"title": "JavaScript Crash Course for Beginners",
"url": "https://youtu.be/hdI2bqOjy3c?t=2",
"url": "https://youtu.be/hdI2bqOjy3c",
"type": "video"
},
{
"title": "Node.js Crash Course",
"url": "https://www.youtube.com/watch?v=fBNz5xF-Kx4",
"type": "video"
},
{
"title": "Node.js Tutorial for Beginners",
"url": "https://www.youtube.com/watch?v=TlB_eWDSMt4",
"type": "video"
}
]

View File

@@ -3954,7 +3954,7 @@
]
},
"ETEUA7jaEGyOEX8tAVNWs": {
"title": "Processes and Threads",
"title": "Porcesses and Threads",
"description": "Processes and threads are the basic building blocks of a computer program. They are the smallest units of execution in a program. A process is an instance of a program that is being executed. A thread is a sequence of instructions within a process that can be executed independently of other code.\n\nVisit the following resources to learn more:",
"links": [
{

View File

@@ -1503,7 +1503,7 @@
},
"c2kY3wZVFKZYxMARhLIwO": {
"title": "SIEM",
"description": "SIEM, short for Security Information and Event Manager, is a term used to describe tools that greatly increases visibility into a network or system. It does this by monitoring, filtering, collecting, normalizing, and correlating vast amounts of data such as logs, and neatly presents it via an interface/dashboard.\n\nOrganizations leverage SIEMs to monitor and thus identify, protect, and respond to potential threats in their environment.\n\nFor hands-on experience, you should consider setting up a SIEM in your own environment. There are some commercial tools that you can try out for free, and there are also open source alternatives, such as Wazuh or LevelBlue OSSIM (AlienVault).\n\nVisit the following resources to learn more:",
"description": "SIEM, short for Security Information and Event Manager, is a term used to describe tools that greatly increases visibility into a network or system. It does this by monitoring, filtering, collecting, normalizing, and correlating vast amounts of data such as logs, and neatly presents it via an interface/dashboard.\n\nOrganizations leverage SIEMs to monitor and thus identify, protect, and respond to potential threats in their environment.\n\nFor hands-on experience, you should consider setting up a SIEM in your own environment. A common stack widely used for various purposes across the industry is the ELK-stack.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Security 101: What is a SIEM? - Microsoft",
@@ -1511,22 +1511,12 @@
"type": "article"
},
{
"title": "SIEM Explained - Professor Messer",
"url": "https://www.youtube.com/watch?v=JEcETdy5WxU",
"type": "video"
"title": "Using the ELK stack for SIEM",
"url": "https://logz.io/blog/elk-siem/",
"type": "article"
},
{
"title": "Wazuh | Open source SIEM",
"url": "https://www.youtube.com/watch?v=3CaG2GI1kn0",
"type": "video"
},
{
"title": "Splunk | The Complete Beginner Tutorial",
"url": "https://www.youtube.com/playlist?list=PLY2f3p7xyMiTUbUo0A_lBFEwj6KdH0nFy",
"type": "video"
},
{
"title": "Elastic Security | Build a powerful home SIEM",
"title": "Build a powerful home SIEM",
"url": "https://www.youtube.com/watch?v=2XLzMb9oZBI",
"type": "video"
}
@@ -1709,7 +1699,7 @@
},
"9rmDvycXFcsGOq3v-_ziD": {
"title": "S/MIME",
"description": "**S/MIME** stands for Secure/Multipurpose Internet Mail Extensions, and it is a cryptographic protocol that enhances the security of business emails through encryption and digital signatures. It allows users to encrypt emails and digitally sign them to verify the senders identity.\n\nAdvantages of S/MIME\n--------------------\n\n* **Verification**: Confirms the senders identity.\n \n* **Confidentiality**: Protects the content from unauthorized access.\n \n* **Integrity**: Ensures the message has not been altered.\n \n* **Secure Data Transfer**: Safely transmits files like images, audio, videos, and documents.\n \n* **Non-repudiation**: Prevents the sender from denying the origin of the message.\n \n\nHow S/MIME Works\n----------------\n\nS/MIME enables the transmission of non-ASCII data via the Secure Mail Transfer Protocol (SMTP). It securely sends various data files, including music, video, and images, using encryption. Data encrypted with a public key can only be decrypted by the recipients private key, ensuring secure end-to-end communication.",
"description": "",
"links": []
},
"3140n5prZYySsuBHjqGOJ": {
@@ -1841,7 +1831,7 @@
},
"rxzcAzHjzIc9lkWSw0fef": {
"title": "VirusTotal",
"description": "VirusTotal's main feature is multi-scanning using over 70 antivirus scanners to generate a cumulative report on whether a file is malicious. It also stores file hashes, eliminating the need to rescan previously uploaded files. Researchers can comment in the community, sharing their analysis and insights into malware for others to benefit from.\n\nVirusTotal's aggregated data comes from various antivirus engines, website scanners, file and URL analysis tools, and user contributions. These tools serve diverse purposes, including heuristic engines, known-bad signatures, metadata extraction, and identification of malicious signals.\n\nAdditionally, VirusTotal offers services to search by file hash, IP address, and URL, which are also scanned. For more comprehensive features, VirusTotal provides Premium services such as Intelligence & Hunting.\n\nVisit the following resources to learn more:",
"description": "",
"links": []
},
"h__KxKa0Q74_egY7GOe-L": {
@@ -1861,14 +1851,8 @@
},
"lMiW2q-b72KUl-2S7M6Vb": {
"title": "urlscan",
"description": "**[urlscan.io](http://urlscan.io)** is a free service to scan and analyze websites. When a URL is submitted to [urlscan.io](http://urlscan.io), an automated process will browse to the URL like a regular user and record the activity that this page navigation creates. This includes the domains and IPs contacted, the resources (JavaScript, CSS, etc) requested from those domains, as well as additional information about the page itself. [urlscan.io](http://urlscan.io) will take a screenshot of the page, record the DOM content, JavaScript global variables, cookies created by the page, and a myriad of other observations. If the site is targeting the users one of the more than 900 brands tracked by [urlscan.io](http://urlscan.io), it will be highlighted as potentially malicious in the scan results.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "urlscan.io",
"url": "https://urlscan.io/",
"type": "article"
}
]
"description": "",
"links": []
},
"-RnlvUltJ9IDtH0HEnMbN": {
"title": "WHOIS",
@@ -2112,19 +2096,8 @@
},
"LfWJJaT3fv0p6fUeS8b84": {
"title": "Deauth Attack",
"description": "A Deauthentication (Deauth) Attack is a type of denial-of-service (DoS) attack specific to wireless networks. It involves sending fake deauthentication frames to a Wi-Fi client or access point, forcing the client to disconnect from the network. The attacker uses this technique to disrupt the communication between the client and the access point, often with the intention of capturing data, launching further attacks, or simply causing disruption.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Wi-Fi Deauthentication Attack",
"url": "https://medium.com/@balaramapunna123/wi-fi-deauthentication-attack-76cdd91d5fc",
"type": "article"
},
{
"title": "Deauthentication Attacks",
"url": "https://www.baeldung.com/cs/deauthentication-attacks",
"type": "article"
}
]
"description": "",
"links": []
},
"u4hySof6if5hiONSaW-Uf": {
"title": "VLAN Hopping",
@@ -2133,18 +2106,12 @@
},
"Ee7LfbhwJbiWjJ3b_bbni": {
"title": "Rogue Access Point",
"description": "A Rogue Access Point (Rogue AP) is an unauthorized wireless access point installed on a secure network without the network administrator's knowledge or consent. These devices can be set up by malicious actors to intercept, steal, or manipulate network traffic, or by employees who unintentionally compromise network security by setting up their own wireless access points.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Rogue access points",
"url": "https://www.khanacademy.org/computing/computers-and-internet/xcae6f4a7ff015e7d:online-data-security/xcae6f4a7ff015e7d:cyber-attacks/a/rogue-access-points-mitm-attacks",
"type": "article"
}
]
"description": "",
"links": []
},
"n8ZOZxNhlnw7DpzoXe_f_": {
"title": "Buffer Overflow",
"description": "A Buffer Overflow is a type of vulnerability that occurs when a program or process attempts to write more data to a buffer—a temporary storage area in memory—than it can hold. This overflow can cause the extra data to overwrite adjacent memory locations, potentially leading to unintended behavior, crashes, or security breaches.\n\nVisit the following resources to learn more:",
"description": "",
"links": []
},
"nOND14t7ISgSH3zNpV3F8": {
@@ -2191,14 +2158,8 @@
},
"mIX8PsIGuwgPCGQZ6ok2H": {
"title": "Replay Attack",
"description": "A Replay Attack is a type of network attack where an attacker intercepts and retransmits legitimate communication data, often with the aim of gaining unauthorized access to a system or performing unauthorized actions. In this attack, the attacker captures a valid data transmission and then \"replays\" it later, without needing to decrypt or alter the data, to trick the recipient into thinking it's a legitimate request.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "What Is a Replay Attack?",
"url": "https://usa.kaspersky.com/resource-center/definitions/replay-attack",
"type": "article"
}
]
"description": "",
"links": []
},
"sMuKqf27y4iG0GrCdF5DN": {
"title": "Pass the Hash",
@@ -2207,55 +2168,13 @@
},
"L0ROYh2DNlkybNDO2ezJY": {
"title": "Directory Traversal",
"description": "Directory Traversal, also known as Path Traversal, is a vulnerability that allows attackers to read files on a system without proper authorization. These attacks typically exploit unsecured paths using \"../\" (dot-dot-slash) sequences and their variations, or absolute file paths. The attack is also referred to as \"dot-dot-slash,\" \"directory climbing,\" or \"backtracking.\"\n\nWhile Directory Traversal is sometimes combined with other vulnerabilities like Local File Inclusion (LFI) or Remote File Inclusion (RFI), the key difference is that Directory Traversal doesn't execute code, whereas LFI and RFI usually do.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "TryHackMe's room on Path Traversal & File Inclusion",
"url": "https://tryhackme.com/r/room/filepathtraversal",
"type": "course"
},
{
"title": "HackTheBox Academy's module on File Inclusion & Path Traversal",
"url": "https://academy.hackthebox.com/course/preview/file-inclusion",
"type": "course"
},
{
"title": "Portswigger's guide on File Path Traversal",
"url": "https://portswigger.net/web-security/file-path-traversal",
"type": "article"
},
{
"title": "OWASP's article on Path Traversal",
"url": "https://owasp.org/www-community/attacks/Path_Traversal",
"type": "article"
},
{
"title": "Acunetix's article on directory traversal",
"url": "https://www.acunetix.com/websitesecurity/directory-traversal/",
"type": "article"
}
]
"description": "",
"links": []
},
"lv6fI3WeJawuCbwKtMRIh": {
"title": "Stakeholders",
"description": "Stakeholders are individuals or organizations with a right, share, claim, or interest in a system or its characteristics that meet their needs and expectations.\n\n### External Stakeholders:\n\n* Government agencies\n* Policy regulators\n* Partners\n* Suppliers\n\n### Internal Stakeholders:\n\n* Subject matter experts\n* Legal\n* Compliance\n* Senior management\n\nStakeholders vary based on the organization, making their identification essential. They must be notified according to the organization's playbook for escalating problems and providing updates. Not all stakeholders are equal, some may require a less technical report highlighting the main points, while others will need a full technical report.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "TryHackMe room on Cyber Governance and regulation",
"url": "https://tryhackme.com/r/room/cybergovernanceregulation",
"type": "course"
},
{
"title": "NIST Publication on Engineering Trustworthy Secure Systems",
"url": "https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-160v1r1.pdf",
"type": "article"
},
{
"title": "NIST Glossary",
"url": "https://csrc.nist.gov/glossary/term/stakeholder",
"type": "article"
}
]
"description": "",
"links": []
},
"05tH6WhToC615JTFN-TPc": {
"title": "HR",

View File

@@ -11,29 +11,8 @@
},
"Lsapbmg-eMIYJAHpV97nO": {
"title": "Types of Data Analytics",
"description": "Data Analytics has proven to be a critical part of decision-making in modern business ventures. It is responsible for discovering, interpreting, and transforming data into valuable information. Different types of data analytics look at past, present, or predictive views of business operations.\n\nData Analysts, as ambassadors of this domain, employ these types, to answer various questions:\n\n* Descriptive Analytics _(what happened in the past?)_\n* Diagnostic Analytics _(why did it happened in the past?)_\n* Predictive Analytics _(what will happen in the future?)_\n* Prescriptive Analytics _(how can we make it happen?)_\n\nUnderstanding these types gives data analysts the power to transform raw datasets into strategic insights.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Data Analytics and its type",
"url": "https://www.geeksforgeeks.org/data-analytics-and-its-type/",
"type": "article"
},
{
"title": "The 4 Types of Data Analysis: Ultimate Guide",
"url": "https://careerfoundry.com/en/blog/data-analytics/different-types-of-data-analysis/",
"type": "article"
},
{
"title": "Descriptive vs Diagnostic vs Predictive vs Prescriptive Analytics: What's the Difference?",
"url": "https://www.youtube.com/watch?v=QoEpC7jUb9k",
"type": "video"
},
{
"title": "Types of Data Analytics",
"url": "https://www.youtube.com/watch?v=lsZnSgxMwBA",
"type": "video"
}
]
"description": "Data Analytics has proven to be a critical part of decision-making in modern business ventures. It is responsible for discovering, interpreting, and transforming data into valuable information. Different types of data analytics look at past, present, or predictive views of business operations.\n\nData Analysts, as ambassadors of this domain, employ these types, which are namely Descriptive Analytics, Diagnostic Analytics, Predictive Analytics and Prescriptive Analytics, to answer various questions — What happened? Why did it happen? What could happen? And what should we do next? Understanding these types gives data analysts the power to transform raw datasets into strategic insights.",
"links": []
},
"hWDh0ooidbqZb000ENVok": {
"title": "Descriptive Analytics",
@@ -157,12 +136,12 @@
"description": "The visualization of data is an essential skill in the toolkit of every data analyst. This practice is about transforming complex raw data into a graphical format that allows for an easier understanding of large data sets, trends, outliers, and important patterns. Whether pie charts, line graphs, bar graphs, or heat maps, data visualization techniques not only streamline data analysis, but also facilitate a more effective communication of the findings to others. This key concept underscores the importance of presenting data in a digestible and visually appealing manner to drive data-informed decision making in an organization.\n\nLearn more from the following resources:",
"links": [
{
"title": "Data visualization beginner's guide",
"title": "Data visualisation beginner's guide",
"url": "https://www.tableau.com/en-gb/learn/articles/data-visualization",
"type": "article"
},
{
"title": "Data Visualization in 2024",
"title": "Data Visualisation in 2024",
"url": "https://www.youtube.com/watch?v=loYuxWSsLNc",
"type": "video"
}

View File

@@ -1037,11 +1037,6 @@
"title": "Docker",
"description": "Docker is a platform for working with containerized applications. Among its features are a daemon and client for managing and interacting with containers, registries for storing images, and a desktop application to package all these features together.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Visit Dedicated Docker Roadmap",
"url": "https://roadmap.sh/docker",
"type": "article"
},
{
"title": "Docker Documentation",
"url": "https://docs.docker.com/",

View File

@@ -235,11 +235,36 @@
"title": "HTML",
"description": "HTML stands for HyperText Markup Language. It is used on the frontend and gives the structure to the webpage which you can style using CSS and make interactive using JavaScript.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Interactive HTML Course",
"url": "https://github.com/denysdovhan/learnyouhtml",
"type": "opensource"
},
{
"title": "W3Schools: Learn HTML",
"url": "https://www.w3schools.com/html/html_intro.asp",
"type": "article"
},
{
"title": "htmlreference.io: All HTML elements at a glance",
"url": "https://htmlreference.io/",
"type": "article"
},
{
"title": "HTML For Beginners The Easy Way",
"url": "https://html.com",
"type": "article"
},
{
"title": "Web Development Basics",
"url": "https://internetingishard.netlify.app/html-and-css/index.html",
"type": "article"
},
{
"title": "You don't need JavaScript for that",
"url": "https://www.htmhell.dev/adventcalendar/2023/2/",
"type": "article"
},
{
"title": "Explore top posts about HTML",
"url": "https://app.daily.dev/tags/html?ref=roadmapsh",
@@ -254,6 +279,11 @@
"title": "HTML Full Course - Build a Website Tutorial",
"url": "https://www.youtube.com/watch?v=pQN-pnXPaVg",
"type": "video"
},
{
"title": "HTML Tutorial for Beginners: HTML Crash Course",
"url": "https://www.youtube.com/watch?v=qz0aGYrrlhU",
"type": "video"
}
]
},
@@ -266,15 +296,30 @@
"url": "https://www.w3schools.com/html/html_intro.asp",
"type": "article"
},
{
"title": "MDN Docs: Getting Started with HTML ",
"url": "https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting_started",
"type": "article"
},
{
"title": "web.dev: Learn HTML",
"url": "https://web.dev/learn/html",
"type": "article"
},
{
"title": "HTML Cheatsheet",
"url": "https://htmlcheatsheet.com",
"type": "article"
},
{
"title": "HTML Full Course - Build a Website Tutorial",
"url": "https://www.youtube.com/watch?v=pQN-pnXPaVg",
"type": "video"
},
{
"title": "HTML Tutorial for Beginners: HTML Crash Course",
"url": "https://www.youtube.com/watch?v=qz0aGYrrlhU",
"type": "video"
}
]
},
@@ -292,6 +337,16 @@
"url": "https://www.w3schools.com/html/html5_semantic_elements.asp",
"type": "article"
},
{
"title": "How To Write Semantic HTML",
"url": "https://hackernoon.com/how-to-write-semantic-html-dkq3ulo",
"type": "article"
},
{
"title": "Semantic HTML: What It Is and How It Improves Your Site",
"url": "https://blog.hubspot.com/website/semantic-html",
"type": "article"
},
{
"title": "Semantic Markup",
"url": "https://html.com/semantic-markup",
@@ -301,6 +356,11 @@
"title": "Semantic HTML - web.dev",
"url": "https://web.dev/learn/html/semantic-html/",
"type": "article"
},
{
"title": "Explore top posts about HTML",
"url": "https://app.daily.dev/tags/html?ref=roadmapsh",
"type": "article"
}
]
},
@@ -339,11 +399,31 @@
"url": "https://www.w3schools.com/accessibility/index.php",
"type": "article"
},
{
"title": "A Complete Guide To Accessible Front-End Components",
"url": "https://www.smashingmagazine.com/2021/03/complete-guide-accessible-front-end-components/",
"type": "article"
},
{
"title": "MDN Accessibility",
"url": "https://developer.mozilla.org/en-US/docs/Web/Accessibility",
"type": "article"
},
{
"title": "Accessibility for Developers by Google",
"url": "https://web.dev/accessibility",
"type": "article"
},
{
"title": "Web Accessibility by Udacity",
"url": "https://www.udacity.com/course/web-accessibility--ud891",
"type": "article"
},
{
"title": "Accessibility as an Essential Part of the Inclusive Developer Experience",
"url": "https://thenewstack.io/accessibility-as-an-essential-part-of-the-inclusive-developer-experience/",
"type": "article"
},
{
"title": "Explore top posts about Accessibility",
"url": "https://app.daily.dev/tags/accessibility?ref=roadmapsh",
@@ -360,11 +440,31 @@
"title": "SEO Basics",
"description": "SEO or Search Engine Optimization is the technique used to optimize your website for better rankings on search engines such as Google, Bing etc.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "SEO Guide",
"url": "https://github.com/seo/guide",
"type": "opensource"
},
{
"title": "Google Search Central — SEO Docs",
"url": "https://developers.google.com/search/docs",
"type": "article"
},
{
"title": "8 Must-Know SEO Best Practices For Developers",
"url": "https://neilpatel.com/blog/seo-developers/",
"type": "article"
},
{
"title": "SEO for Developers",
"url": "https://medium.com/welldone-software/seo-for-developers-a-quick-overview-5b5b7ce34679",
"type": "article"
},
{
"title": "Learning SEO",
"url": "https://learningseo.io/",
"type": "article"
},
{
"title": "Explore top posts about SEO",
"url": "https://app.daily.dev/tags/seo?ref=roadmapsh",
@@ -386,16 +486,46 @@
"title": "CSS",
"description": "CSS or Cascading Style Sheets is the language used to style the frontend of any website. CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "The Odin Project",
"url": "https://www.theodinproject.com//",
"type": "article"
},
{
"title": "What The Flexbox!",
"url": "https://flexbox.io/",
"type": "article"
},
{
"title": "W3Schools — Learn CSS",
"url": "https://www.w3schools.com/css/",
"type": "article"
},
{
"title": "cssreference.io: All CSS properties at a glance",
"url": "https://cssreference.io/",
"type": "article"
},
{
"title": "Web.dev by Google — Learn CSS",
"url": "https://web.dev/learn/css/",
"type": "article"
},
{
"title": "Learn to Code HTML & CSS",
"url": "https://learn.shayhowe.com/html-css/building-your-first-web-page/",
"type": "article"
},
{
"title": "Joshw Comeaus CSS Hack Blog Posts",
"url": "https://www.joshwcomeau.com/",
"type": "article"
},
{
"title": "100 Days CSS Challenge",
"url": "https://100dayscss.com",
"type": "article"
},
{
"title": "Explore top posts about CSS",
"url": "https://app.daily.dev/tags/css?ref=roadmapsh",
@@ -406,10 +536,20 @@
"url": "https://youtu.be/n4R2E7O-Ngo",
"type": "video"
},
{
"title": "CSS Crash Course For Absolute Beginners",
"url": "https://www.youtube.com/watch?v=yfoY53QXEnI",
"type": "video"
},
{
"title": "HTML and CSS Tutorial",
"url": "https://www.youtube.com/watch?v=D-h8L5hgW-w",
"type": "video"
},
{
"title": "CSS Masterclass - Tutorial & Course for Beginners",
"url": "https://www.youtube.com/watch?v=FqmB-Zj2-PA",
"type": "video"
}
]
},
@@ -453,6 +593,11 @@
"title": "Making Layouts",
"description": "Float, grid, flexbox, positioning, display and box model are some of the key topics that are used for making layouts. Use the resources below to learn about these topics:\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Learn CSS Grid for free",
"url": "https://scrimba.com/learn/cssgrid?via=roadmap",
"type": "course"
},
{
"title": "Learn and Practice Flexbox",
"url": "https://flexboxfroggy.com/",
@@ -540,16 +685,41 @@
"title": "JavaScript",
"description": "JavaScript allows you to add interactivity to your pages. Common examples that you may have seen on the websites are sliders, click interactions, popups and so on.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "You Dont Know JS Yet (book series) ",
"url": "https://github.com/getify/You-Dont-Know-JS",
"type": "opensource"
},
{
"title": "Learn the basics of JavaScript",
"url": "https://github.com/workshopper/javascripting",
"type": "opensource"
},
{
"title": "Visit Dedicated JavaScript Roadmap",
"url": "/javascript",
"type": "article"
},
{
"title": "W3Schools JavaScript Tutorial",
"url": "https://www.w3schools.com/js/",
"type": "article"
},
{
"title": "The Modern JavaScript Tutorial",
"url": "https://javascript.info/",
"type": "article"
},
{
"title": "Learn JavaScript: Covered many topics",
"url": "https://www.javascripttutorial.net/",
"type": "article"
},
{
"title": "Eloquent JavaScript textbook",
"url": "https://eloquentjavascript.net/",
"type": "article"
},
{
"title": "Build 30 Javascript projects in 30 days",
"url": "https://javascript30.com/",
@@ -564,6 +734,11 @@
"title": "JavaScript Crash Course for Beginners",
"url": "https://youtu.be/hdI2bqOjy3c?t=2",
"type": "video"
},
{
"title": "Build a Netflix Landing Page Clone with HTML, CSS & JS",
"url": "https://youtu.be/P7t13SGytRk?t=22",
"type": "video"
}
]
},
@@ -1911,16 +2086,46 @@
"title": "TypeScript",
"description": "TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Scrimba — TypeScript Basics",
"url": "https://scrimba.com/learn/typescript?via=roadmap",
"type": "course"
},
{
"title": "Official Website",
"url": "https://www.typescriptlang.org/",
"type": "article"
},
{
"title": "Official Docs for Deep Dives",
"url": "https://www.typescriptlang.org/docs/",
"type": "article"
},
{
"title": "The TypeScript Handbook",
"url": "https://www.typescriptlang.org/docs/handbook/intro.html",
"type": "article"
},
{
"title": "TypeScript Tutorial",
"url": "https://www.tutorialspoint.com/typescript/index.htm",
"type": "article"
},
{
"title": "What Is TypeScript?",
"url": "https://thenewstack.io/what-is-typescript/",
"type": "article"
},
{
"title": "TypeScript Tutorial: Go beyond Hello, World!",
"url": "https://thenewstack.io/typescript-tutorial-go-beyond-hello-world/",
"type": "article"
},
{
"title": "A Guide to Using the Programming Language",
"url": "https://thenewstack.io/typescript-tutorial-a-guide-to-using-the-programming-language/",
"type": "article"
},
{
"title": "Explore top posts about TypeScript",
"url": "https://app.daily.dev/tags/typescript?ref=roadmapsh",

View File

@@ -3,6 +3,11 @@
"title": "HTML",
"description": "HTML stands for HyperText Markup Language. It is used on the frontend and gives the structure to the webpage which you can style using CSS and make interactive using JavaScript.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Interactive HTML Course",
"url": "https://github.com/denysdovhan/learnyouhtml",
"type": "opensource"
},
{
"title": "W3Schools: Learn HTML",
"url": "https://www.w3schools.com/html/html_intro.asp",
@@ -14,13 +19,18 @@
"type": "article"
},
{
"title": "HTML Full Course for Beginners",
"url": "https://youtu.be/mJgBOIoGihA",
"title": "HTML Full Course - Build a Website Tutorial",
"url": "https://www.youtube.com/watch?v=pQN-pnXPaVg",
"type": "video"
},
{
"title": "HTML Full Course - Build a Website Tutorial",
"url": "https://www.youtube.com/watch?v=pQN-pnXPaVg",
"title": "HTML Tutorial for Beginners: HTML Crash Course",
"url": "https://www.youtube.com/watch?v=qz0aGYrrlhU",
"type": "video"
},
{
"title": "HTML and CSS Full Course - Beginner To Pro",
"url": "https://youtu.be/a_iQb1lnAEQ",
"type": "video"
}
]
@@ -35,8 +45,13 @@
"type": "article"
},
{
"title": "Web.dev by Google — Learn CSS",
"url": "https://web.dev/learn/css/",
"title": "Learn to Code HTML & CSS",
"url": "https://learn.shayhowe.com/html-css/building-your-first-web-page/",
"type": "article"
},
{
"title": "What The Flexbox!",
"url": "https://flexbox.io/",
"type": "article"
},
{
@@ -45,24 +60,29 @@
"type": "article"
},
{
"title": "CSS Complete Course",
"url": "https://youtu.be/n4R2E7O-Ngo",
"title": "CSS Crash Course For Absolute Beginners",
"url": "https://www.youtube.com/watch?v=yfoY53QXEnI",
"type": "video"
},
{
"title": "HTML and CSS Tutorial",
"url": "https://www.youtube.com/watch?v=D-h8L5hgW-w",
"type": "video"
},
{
"title": "CSS Masterclass - Tutorial & Course for Beginners",
"url": "https://www.youtube.com/watch?v=FqmB-Zj2-PA",
"type": "video"
}
]
},
"T9PB6WQf-Fa9NXKKvVOy_": {
"title": "JavaScript",
"description": "JavaScript allows you to add interactivity to your pages. Common examples that you may have seen on the websites are sliders, click interactions, popups and so on.\n\nVisit the following resources to learn more:",
"description": "JavaScript allows you to add interactivity to your pages. Common examples that you may have seen on the websites are sliders, click interactions, popups and so on.\n\nVisit the following resources to learn more:\n\nWe also have this [JavaScript roadmap](/javascript). You don't need to follow it right now, just learn from some courses and revisit the roadmap later in your journey.",
"links": [
{
"title": "Visit Dedicated JavaScript Roadmap",
"url": "/javascript",
"title": "W3Schools JavaScript Tutorial",
"url": "https://www.w3schools.com/js/",
"type": "article"
},
{
@@ -71,8 +91,8 @@
"type": "article"
},
{
"title": "Build 30 Javascript projects in 30 days",
"url": "https://javascript30.com/",
"title": "Exploring JS: JavaScript books for programmers",
"url": "https://exploringjs.com/",
"type": "article"
},
{
@@ -84,6 +104,11 @@
"title": "JavaScript Crash Course for Beginners",
"url": "https://youtu.be/hdI2bqOjy3c?t=2",
"type": "video"
},
{
"title": "Build a Netflix Landing Page Clone with HTML, CSS & JS",
"url": "https://youtu.be/P7t13SGytRk",
"type": "video"
}
]
},

View File

@@ -772,25 +772,13 @@
},
"sz1047M8_kScjth84yPwU": {
"title": "Decision Tree Learning",
"description": "`Decision Tree Learning` is an important concept in game development, particularly in the development of artificial intelligence for game characters. It is a kind of machine learning method that is based on using decision tree models to predict or classify information. A decision tree is a flowchart-like model, where each internal node denotes a test on an attribute, each branch represents an outcome of that test, and each leaf node holds a class label (decision made after testing all attributes). By applying decision tree learning models, computer-controlled characters can make decisions based on different conditions or states. They play a key role in creating complex and interactive gameplay experiences, by enabling game characters to adapt to the player's actions and the ever-changing game environment.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Decision trees - A friendly introduction",
"url": "https://www.youtube.com/watch?v=HkyWAhr9v8g",
"type": "video"
}
]
"description": "`Decision Tree Learning` is an important concept in game development, particularly in the development of artificial intelligence for game characters. It is a kind of machine learning method that is based on using decision tree models to predict or classify information. A decision tree is a flowchart-like model, where each internal node denotes a test on an attribute, each branch represents an outcome of that test, and each leaf node holds a class label (decision made after testing all attributes). By applying decision tree learning models, computer-controlled characters can make decisions based on different conditions or states. They play a key role in creating complex and interactive gameplay experiences, by enabling game characters to adapt to the player's actions and the ever-changing game environment.",
"links": []
},
"ltkEyfuDxExs7knqs79ya": {
"title": "Deep Learning",
"description": "Deep Learning is a sub-field of machine learning, inspired by the structure and function of the human brain, specifically designed to process complex input/output transformations. It uses artificial neural networks with many layers (hence the term 'deep' learning) to model complex, non-linear hypotheses and discover hidden patterns within large datasets. Deep learning techniques are crucial in game development, primarily in creating intelligent behaviors and features in gaming agents, procedural content generation, and player profiling. You might have heard about the uses of deep learning technologies in popular, cutting-edge games like Google DeepMind's AlphaGo. Coding languages like Python, R, and frameworks like TensorFlow, Keras, and PyTorch are commonly used for deep learning tasks. Learning Deep Learning can be a prominent game-changer in your game development journey.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "But what is a neural network? | Chapter 1, Deep learning",
"url": "https://www.youtube.com/watch?v=aircAruvnKk",
"type": "video"
}
]
"description": "Deep Learning is a sub-field of machine learning, inspired by the structure and function of the human brain, specifically designed to process complex input/output transformations. It uses artificial neural networks with many layers (hence the term 'deep' learning) to model complex, non-linear hypotheses and discover hidden patterns within large datasets. Deep learning techniques are crucial in game development, primarily in creating intelligent behaviors and features in gaming agents, procedural content generation, and player profiling. You might have heard about the uses of deep learning technologies in popular, cutting-edge games like Google DeepMind's AlphaGo. Coding languages like Python, R, and frameworks like TensorFlow, Keras, and PyTorch are commonly used for deep learning tasks. Learning Deep Learning can be a prominent game-changer in your game development journey.",
"links": []
},
"AoH2r4EOHyZd8YaV24rBk": {
"title": "Artificial Neural Network",
@@ -866,13 +854,7 @@
},
"YrQgfjsdLCIUxrwflpEHO": {
"title": "Microsurface Scattering",
"description": "Microsurface scattering, also known as sub-surface scattering, is an important phenomenon in Physically Based Rendering (PBR). This process involves the penetration of light into the surface of a material, where it is scattered by interacting with the material. In other words, when light strikes an object, rather than simply bouncing off the surface, some of it goes into the object and gets scattered around inside before getting re-emitted. It is key to achieving more realistic rendering of translucent materials like skin, marble, milk, and more. Consider it essential for replicating how light interacts with real-world materials in a convincing manner in your game.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "The 4 main types of subsurface scattering",
"url": "https://www.youtube.com/watch?v=GkjvYSbGHg4",
"type": "video"
}
]
"description": "Microsurface scattering, also known as sub-surface scattering, is an important phenomenon in Physically Based Rendering (PBR). This process involves the penetration of light into the surface of a material, where it is scattered by interacting with the material. In other words, when light strikes an object, rather than simply bouncing off the surface, some of it goes into the object and gets scattered around inside before getting re-emitted. It is key to achieving more realistic rendering of translucent materials like skin, marble, milk, and more. Consider it essential for replicating how light interacts with real-world materials in a convincing manner in your game.",
"links": []
}
}

View File

@@ -4,7 +4,7 @@
"description": "JavaScript, often abbreviated JS, is a programming language that is one of the core technologies of the World Wide Web, alongside HTML and CSS. It lets us add interactivity to pages e.g. you might have seen sliders, alerts, click interactions, popups, etc on different websites -- all of that is built using JavaScript. Apart from being used in the browser, it is also used in other non-browser environments as well such as Node.js for writing server-side code in JavaScript, Electron for writing desktop applications, React Native for mobile applications, and so on.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "You Don't Know JS Yet (book series)",
"title": "You Dont Know JS Yet (book series)",
"url": "https://github.com/getify/You-Dont-Know-JS",
"type": "opensource"
},
@@ -200,7 +200,7 @@
"type": "article"
},
{
"title": "Understanding Hoisting",
"title": "Understanding hoisting ",
"url": "https://www.digitalocean.com/community/tutorials/understanding-hoisting-in-javascript",
"type": "article"
},
@@ -307,7 +307,7 @@
},
"q85z6x1Lc-yLWepwtIT2_": {
"title": "const",
"description": "Constants are block-scoped, much like variables declared using the `let` keyword. The value of a constant can't be changed through reassignment (i.e. by using the assignment operator), and it can't be re-declared (i.e. through a variable declaration). However, if a constant is an object or array its properties or items can be updated or removed.\n\nVisit the following resources to learn more:",
"description": "Constants are block-scoped, much like variables declared using the `let` keyword. The value of a constant can't be changed through reassignment (i.e. by using the assignment operator), and it can't be redeclared (i.e. through a variable declaration). However, if a constant is an object or array its properties or items can be updated or removed.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "JavaScript Constants - CodeGuage",
@@ -360,7 +360,7 @@
},
"oC4o6GLEES_nUgCJu9Q6I": {
"title": "Global",
"description": "Variables declared Globally (outside any function) have Global Scope. Global variables can be accessed from anywhere in a JavaScript program. Variables declared with `var`, `let` and `const` are quite similar when declared outside a block.\n\nNote\n----\n\nIf you assign a value to a variable that has not been declared i.e `potato = true` it will automatically become a _GLOBAL_ variable.\n\nVisit the following resources to learn more:",
"description": "Variables declared Globally (outside any function) have Global Scope. Global variables can be accessed from anywhere in a JavaScript program. Variables declared with `var`, `let` and `const` are quite similar when declared outside a block.\n\n### Note:\n\nIf you assign a value to a variable that has not been declared i.e `potato = true` it will automatically become a _GLOBAL_ variable.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "JavaScript Scope",
@@ -445,7 +445,7 @@
},
"GZ_SXsWmP7AsXRTc4WUMw": {
"title": "number",
"description": "The `Number` data type in JavaScript represents floating-point numbers, such as 37 or -9.25. The `Number` constructor provides constants and methods to work with numbers, and values of other types can be converted to numbers using the `Number()` function.\n\nExample\n-------\n\n let num1 = 255; // integer\n let num2 = 255.0; // floating-point number with no fractional part\n let num3 = 0xff; // hexadecimal notation\n let num4 = 0b11111111; // binary notation\n let num5 = 0.255e3; // exponential notation\n \n console.log(num1 === num2); // true\n console.log(num1 === num3); // true\n console.log(num1 === num4); // true\n console.log(num1 === num5); // true\n \n\nIn this example:\n\n* `255` and `255.0` are equivalent, as JavaScript treats both as the same number.\n* `0xff` represents `255` in hexadecimal notation.\n* `0b11111111` represents `255` in binary notation.\n* `0.255e3` is `255` in exponential notation.\n* All these different representations are equal to `255` in JavaScript.",
"description": "The `Number` data type in JavaScript represents floating-point numbers, such as 37 or -9.25. The `Number` constructor provides constants and methods to work with numbers, and values of other types can be converted to numbers using the `Number()` function.\n\n### Example\n\n let num1 = 255; // integer\n let num2 = 255.0; // floating-point number with no fractional part\n let num3 = 0xff; // hexadecimal notation\n let num4 = 0b11111111; // binary notation\n let num5 = 0.255e3; // exponential notation\n \n console.log(num1 === num2); // true\n console.log(num1 === num3); // true\n console.log(num1 === num4); // true\n console.log(num1 === num5); // true\n \n\nIn this example:\n\n* `255` and `255.0` are equivalent, as JavaScript treats both as the same number.\n* `0xff` represents `255` in hexadecimal notation.\n* `0b11111111` represents `255` in binary notation.\n* `0.255e3` is `255` in exponential notation.\n* All these different representations are equal to `255` in JavaScript.",
"links": []
},
"6lUF0neW1piiP1RsaVxEX": {
@@ -580,12 +580,12 @@
"description": "You can use the typeOf operator to find the data type of a JavaScript variable. It returns a string indicating the type of provided operand's value.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "typeof Reference",
"title": "Typeof Reference",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof",
"type": "article"
},
{
"title": "typeof Live Examples",
"title": "Typeof Live Examples",
"url": "https://www.w3schools.com/js/tryit.asp?filename=tryjs_typeof_all",
"type": "article"
}
@@ -695,7 +695,7 @@
"type": "article"
},
{
"title": "What you need to know about JavaScript Implicit Coercion",
"title": "What you need to know about Javascripts Implicit Coercion",
"url": "https://dev.to/promisetochi/what-you-need-to-know-about-javascripts-implicit-coercion-e23",
"type": "article"
}
@@ -1245,7 +1245,7 @@
},
"-z-4VTaC3tOThqChgyoMs": {
"title": "Error Objects",
"description": "When a runtime error occurs, a new `Error` object is created and thrown. With this `Error` object, we can determine the type of the Error and handle it according to its type.\n\nTypes of Errors\n---------------\n\nBesides error constructors, Javascript also has other core Error constructors. Like\n\n* AggregateError - A collection of errors thrown simultaneously.\n* EvalError - An error occurred during the evaluation of a JavaScript expression.\n* InternalError - An internal JavaScript error, often indicating a bug in the engine.\n* RangeError - A value is outside the allowed range for a given operation.\n* ReferenceError - A variable or object is referenced before it's declared or doesn't exist.\n* SyntaxError - The code contains incorrect syntax, preventing it from being parsed.\n\nExample\n-------\n\n try {\n willGiveErrorSometime();\n } catch (error) {\n if (error instanceof RangeError) {\n rangeErrorHandler(error);\n } else if (error instanceof ReferenceError) {\n referenceErrorHandle(error);\n } else {\n errorHandler(error);\n }\n }\n \n\nVisit the following resources to learn more:",
"description": "When a runtime error occurs, a new `Error` object is created and thrown. With this `Error` object, we can determine the type of the Error and handle it according to its type.\n\nTypes of Errors:\n----------------\n\nBesides error constructors, Javascript also has other core Error constructors.\n\n* [@article@AggregateError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError)\n* [@article@EvalError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError)\n* [@article@InternalError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/InternalError)\n* [@article@RangeError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError)\n* [@article@ReferenceError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError)\n* [@article@SyntaxError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError)\n\nExample\n-------\n\n try {\n willGiveErrorSometime();\n } catch (error) {\n if (error instanceof RangeError) {\n rangeErrorHandler(error);\n } else if (error instanceof ReferenceError) {\n referenceErrorHandle(error);\n } else {\n errorHandler(error);\n }\n }\n \n\nVisit the following resources to learn more:",
"links": [
{
"title": "Error Object - MDN",
@@ -1256,36 +1256,6 @@
"title": "Control flow & Error handling - MDN",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling",
"type": "article"
},
{
"title": "AggregateError",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError",
"type": "article"
},
{
"title": "EvalError",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError",
"type": "article"
},
{
"title": "InternalError",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/InternalError",
"type": "article"
},
{
"title": "RangeError",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError",
"type": "article"
},
{
"title": "ReferenceError",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError",
"type": "article"
},
{
"title": "SyntaxError",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError",
"type": "article"
}
]
},
@@ -1445,7 +1415,7 @@
]
},
"k9rSR-YQ8B_iRcXNm2btP": {
"title": "Unary Operators",
"title": "Unary Opeartors",
"description": "JavaScript Unary Operators are the special operators that consider a single operand and perform all the types of operations on that single operand. These operators include unary plus, unary minus, prefix increments, postfix increments, prefix decrements, and postfix decrements.\n\nVisit the following resources to learn more:",
"links": [
{
@@ -1510,7 +1480,7 @@
},
"fr0NChxMXLpJizyMhXcXS": {
"title": "Arrow Functions",
"description": "Arrow Function is a new way of creating functions with the '=>' operator with a shorter syntax.\n\nExample\n-------\n\n const sayHello = () => {\n console.log(`Hello from Arrow Function !`);\n }\n \n\nVisit the following resources to learn more:",
"description": "Arrow Function is a new way of creating functions with the '=>' operator with a shorter syntax.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "MDN - Arrow Function Expressions",
@@ -1526,7 +1496,7 @@
},
"YZlCoPvZuX5MmpLOTj5d4": {
"title": "IIFEs",
"description": "Immediately-Invoked Function Expression is a function that is executed immediately after it is created.\n\nExample\n-------\n\n // An Async IIFE\n ( async() => {\n \n const x = 1;\n const y = 9;\n \n console.log(`Hello, The Answer is ${x+y}`);\n \n })();\n \n\nVisit the following resources to learn more:",
"description": "Immediately-Invoked Function Expression is a function that is executed immediately after it is created.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "IIFE — MDN Docs",
@@ -1812,43 +1782,21 @@
"description": "The `call()` method allows you to invoke a function with a given `this` value, and arguments provided individually.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Call Method - MDN Docs",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call",
"title": "Understanding Explicit Binding in JavaScript: Call, Bind, and Apply Methods",
"url": "https://medium.com/@amitsharma_24072/understanding-explicit-binding-in-javascript-call-bind-and-apply-methods-7b6ed0107628",
"type": "article"
}
]
},
"-BtF34cEzI6J8sZCDRlRE": {
"title": "apply",
"description": "The apply() method of Function instances calls this function with a given this value, and arguments provided as an array (or an array-like object).\n\nVisit the following resources to learn more:",
"links": [
{
"title": "apply() - MDN",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply",
"type": "article"
}
]
"description": "",
"links": []
},
"dbercnxXVTJXMpYSDNGb2": {
"title": "bind",
"description": "The `bind()` method in JavaScript allows you to create a new function with a specific context and optionally preset arguments. Unlike `call()` or `apply()`, `bind()` does not immediately invoke the function. Instead, it returns a new function that can be called later, either as a regular function or with additional arguments. This is particularly useful when you want to ensure that a function retains a specific context, regardless of how or when it's invoked.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "bind()",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind",
"type": "article"
},
{
"title": "Function binding",
"url": "https://javascript.info/bind",
"type": "article"
},
{
"title": "Javascript Function Bind()",
"url": "https://www.w3schools.com/js/js_function_bind.asp",
"type": "article"
}
]
"description": "",
"links": []
},
"sFOqx6_7poVIVuXhJVY0E": {
"title": "Asynchronous JavaScript",
@@ -1993,7 +1941,7 @@
},
"PJSdqvh5OBwPCNpn3q_S5": {
"title": "Callback Hell",
"description": "The callback hell is when we try to write asynchronous JavaScript in a way where execution happens visually from top to bottom, creating a code that has a pyramid shape with many **})** at the end.\n\nVisit the following resources to learn more:",
"description": "The callback hell is when we try to write asynchronous JavaScript in a way where execution happens visually from top to bottom, creating a code that has a pyramid shape with many }) at the end.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Callbacks in Callbacks - Pyramid of Doom",
@@ -2056,7 +2004,7 @@
},
"kL5rfWxXe4J44ENru1uJS": {
"title": "Fetch",
"description": "The `fetch()` method in JavaScript is used to request to the server and load the information on the webpages. The request can be of any APIs that return the data of the format JSON or XML. This method returns a promise.\n\nVisit the following resources to learn more:",
"description": "The fetch() method in JavaScript is used to request to the server and load the information on the webpages. The request can be of any APIs that return the data of the format JSON or XML. This method returns a promise.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Fetch MDN Docs",
@@ -2171,7 +2119,7 @@
},
"4EXeGkOpfAViB9Uo4zL6O": {
"title": "CommonJS",
"description": "CommonJS modules are the original way to package JavaScript code for Node.js. Node.js also supports the ESModules standard used by browsers and other JavaScript run-times, but CJS is still widely used in backend Node.js applications. Sometimes these modules will be written with a .cjs extension.\n\nVisit the following resources to learn more:",
"description": "CommonJS modules are the original way to package JavaScript code for Node.js. Node.js also supports the ESModules standard used by browsers and other JavaScript runtimes, but CJS is still widely used in backend Node.js applications. Sometimes these modules will be written with a .cjs extension.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "How the CJS Module System Works",
@@ -2255,7 +2203,7 @@
},
"bhuGtcyqPFKu-900aESYz": {
"title": "DOM APIs",
"description": "With HTML DOM, JavaScript can access and change all the elements of an HTML document such as its attributes, CSS styles, remove elements, add and create new elements on the page. Web API means application programming interface for the web. All browsers have a set of built-in Web APIs to support complex operations, and to help accessing data. Like Geo-location API, Web Storage, Web History and others.\n\nVisit the following resources to learn more:",
"description": "With HTML DOM, JavaScript can access and change all the elements of an HTML document such as its attributes, CSS styles, remove elements, add and create new elements on the page. Web API means application programming inteface for the web. All browsers have a set og built-in Web APIs to support complex operations, and to help accessing data. Like Geolocation API, Web Storage, Web History and others.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "DOM- MDN Docs",
@@ -2287,16 +2235,11 @@
},
"rc5WzBBOm2cus-rQl8EOE": {
"title": "Using Browser DevTools",
"description": "These are a set of tools built into the browser to aid frontend developers diagnose and solve various issues in their applications — such as JavaScript and logical bugs, CSS styling issues or even just making quick temporary alterations to the DOM.\n\nTo enter the dev tools, right click and click **Inspect** (or press `ctrl+shift+c`/`cmd+opt+c`) to enter the Elements panel. Here you can debug CSS and HTML issues. If you want to see logged messages or interact with javascript, enter the **Console** tab from the tabs above (or press `ctrl+shift+j` or `F12` / `cmd+opt+j` to enter it directly). Another very useful feature in the Chrome dev tools is the Lighthouse (for checking performance).\n\nNOTE: This isn't a chrome-specific feature, and most browsers (Chromium based or otherwise) will have their own, largely-similar set of devtools.\n\nVisit the following resources to learn more:",
"description": "These are a set of tools built into the browser to aid frontend developers diagnose and solve various issues in their applications — such as JavaScript and logical bugs, CSS styling issues or even just making quick temporary alterations to the DOM.\n\nTo enter the dev tools, right click and click **Inspect** (or press `ctrl+shift+c`/`cmd+opt+c`) to enter the Elements panel. Here you can debug CSS and HTML issues. If you want to see logged messages or interact with javascript, enter the **Console** tab from the tabs above (or press `ctrl+shift+j` or `F12` /`cmd+opt+j` to enter it directly). Another very useful feature in the Chrome dev tools is the Lighthouse (for checking performance).\n\nNOTE: This isn't a chrome-specific feature, and most browsers (Chromium based or otherwise) will have their own, largely-similar set of devtools.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Official Docs",
"url": "https://developer.chrome.com/docs/devtools/",
"type": "article"
},
{
"title": "Debug JavaScript with Chrome Dev Tools",
"url": "https://developer.chrome.com/docs/devtools/javascript/",
"url": "https://developer.chrome.com/docs/devtools/overview/",
"type": "article"
},
{
@@ -2327,7 +2270,7 @@
"type": "article"
},
{
"title": "Effective Javascript Debugging",
"title": "Effective Javascript Debugging ",
"url": "https://medium.com/swlh/effective-javascript-debugging-memory-leaks-75059b2436f6",
"type": "article"
},
@@ -2350,7 +2293,7 @@
},
"ECxISKUAU7js_JsfSHzud": {
"title": "Debugging Performance",
"description": "Enter the dev tools and check out the Lighthouse tab. This is essentially a series of tests which analyses the currently open website on a bunch of metrics related to performance, page speed, accessibility, etc. Feel free to run the tests by clicking the **Analyze Page Load** button (you might want to do this in an incognito tab to avoid errors arising from extensions you're using). Once you have the results, take your time and read through them (and do click through to the reference pages mentioned alongside each test result to know more about it!)\n\nVisit the following resources to learn more:",
"description": "Enter the dev tools and check out the Lighthouse tab. This is essentially a series of tests which analyses the currently open website on a bunch of metrics related to performance, page speed, accessibility, etc. Feel free to run the tests by clicking the **Analyse Page Load** button (you might want to do this in an incognito tab to avoid errors arising from extensions you're using). Once you have the results, take your time and read through them (and do click through to the reference pages mentioned alongside each test result to know more about it!)\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Analyze runtime performance",

View File

@@ -1616,11 +1616,6 @@
"title": "Drizzle",
"description": "Drizzle lets you build your project the way you want, without interfering with your project or structure. Using Drizzle you can define and manage database schemas in TypeScript, access your data in a SQL-like or relational way, and take advantage of opt-in tools to make your developer experience amazing.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Drizzle Github",
"url": "https://github.com/drizzle-team/drizzle-orm",
"type": "opensource"
},
{
"title": "Drizzle Website",
"url": "https://orm.drizzle.team/",
@@ -1631,6 +1626,11 @@
"url": "https://orm.drizzle.team/docs/overview",
"type": "article"
},
{
"title": "Drizzle Github",
"url": "https://github.com/drizzle-team/drizzle-orm",
"type": "article"
},
{
"title": "Getting Started with Drizzle",
"url": "https://dev.to/franciscomendes10866/getting-started-with-drizzle-orm-a-beginners-tutorial-4782",

View File

@@ -98,6 +98,11 @@
"title": "Data Types",
"description": "PostgreSQL offers a rich and diverse set of data types, catering to a wide range of applications and ensuring data integrity and performance. These include standard numeric types such as integers, floating-point numbers, and serial types for auto-incrementing fields. Character types like VARCHAR and TEXT handle varying lengths of text, while DATE, TIME, and TIMESTAMP support a variety of temporal data requirements. PostgreSQL also supports a comprehensive set of Boolean, enumerated (ENUM), and composite types, enabling more complex data structures. Additionally, it excels with its support for JSON and JSONB data types, allowing for efficient storage and querying of semi-structured data. The inclusion of array types, geometric data types, and the PostGIS extension for geographic data further extends PostgreSQL's versatility, making it a powerful tool for a broad spectrum of data management needs.\n\nLearn more from the following resources:",
"links": [
{
"title": "",
"url": "https://www.instaclustr.com/blog/postgresql-data-types-mappings-to-sql-jdbc-and-java-data-types/",
"type": "article"
},
{
"title": "Data Types",
"url": "https://www.postgresql.org/docs/current/datatype.html",
@@ -107,11 +112,6 @@
"title": "An introduction to PostgreSQL data types",
"url": "https://www.prisma.io/dataguide/postgresql/introduction-to-data-types",
"type": "article"
},
{
"title": "PostgreSQL® Data Types: Mappings to SQL, JDBC, and Java Data Types",
"url": "https://www.instaclustr.com/blog/postgresql-data-types-mappings-to-sql-jdbc-and-java-data-types/",
"type": "article"
}
]
},

View File

@@ -95,17 +95,6 @@
"title": "Type Conversion and Casting",
"url": "https://www.programiz.com/python-programming/type-conversion-and-casting",
"type": "article"
}
]
},
"fNTb9y3zs1HPYclAmu_Wv": {
"title": "Exceptions",
"description": "Python exceptions are events that occur during the execution of a program and disrupt the normal flow of the program's instructions. When an exception is raised, it indicates that an error has occurred. Python provides a way to handle these exceptions using try-except blocks, allowing developers to manage errors gracefully and ensure the program can continue or exit smoothly.",
"links": [
{
"title": "Exceptions Documentation",
"url": "https://docs.python.org/3/tutorial/errors.html#exceptions",
"type": "article"
},
{
"title": "Python Exceptions: An Introduction",
@@ -126,6 +115,17 @@
"title": "Python Try Except",
"url": "https://www.w3schools.com/python/python_try_except.asp",
"type": "article"
}
]
},
"fNTb9y3zs1HPYclAmu_Wv": {
"title": "Exceptions",
"description": "Python exceptions are events that occur during the execution of a program and disrupt the normal flow of the program's instructions. When an exception is raised, it indicates that an error has occurred. Python provides a way to handle these exceptions using try-except blocks, allowing developers to manage errors gracefully and ensure the program can continue or exit smoothly.",
"links": [
{
"title": "Exceptions Documentation",
"url": "https://docs.python.org/3/tutorial/errors.html#exceptions",
"type": "article"
},
{
"title": "Exception Handling in Python",
@@ -227,16 +227,6 @@
"title": "Loops in Python",
"url": "https://www.geeksforgeeks.org/loops-in-python/",
"type": "article"
},
{
"title": "Python \"while\" Loops (Indefinite Iteration)",
"url": "https://realpython.com/python-while-loop/",
"type": "article"
},
{
"title": "Python \"for\" Loops (Definite Iteration)",
"url": "https://realpython.com/python-for-loop/#the-guts-of-the-python-for-loop",
"type": "article"
}
]
},
@@ -1217,16 +1207,10 @@
}
]
},
"DS6nuAUhUYcqiJDmQisKM": {
"black@DS6nuAUhUYcqiJDmQisKM.md": {
"title": "black",
"description": "black is a code formatter for Python. It is a tool that automatically formats Python code to adhere to the PEP 8 style guide. It is a great tool to use in your Python projects to ensure that your code is formatted consistently and correctly.",
"links": [
{
"title": "black documentation",
"url": "https://black.readthedocs.io/en/stable/",
"type": "article"
}
]
"description": "",
"links": []
},
"tsh_vbhzKz1-H9Vh69tsK": {
"title": "yapf",

View File

@@ -586,7 +586,7 @@
},
"w3bNp7OkehI1gjx8NzlC8": {
"title": "useMemo",
"description": "`useMemo` is a React hook that memoizes the result of a function. It is used to optimize performance by caching the result of a function and returning the cached result when the inputs to the function have not changed.\n\nLearn more from the following resources:",
"description": "`useMemo` is a React hook that memorizes the result of a function. It is used to optimize performance by caching the result of a function and returning the cached result when the inputs to the function have not changed.\n\nLearn more from the following resources:",
"links": [
{
"title": "useMemo Docs",
@@ -1618,26 +1618,21 @@
},
"ElgRwv5LSVg5FXGx-2K2s": {
"title": "TypeScript",
"description": "TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.\n\nVisit the following resources to learn more:",
"description": "TypeScript is a free and open-source high-level programming language developed by Microsoft that adds static typing with optional type annotations to JavaScript. It is designed for the development of large applications and transpiles to JavaScript. Because TypeScript is a superset of JavaScript, all JavaScript programs are syntactically valid TypeScript, but they can fail to type-check for safety reasons.\n\nTypeScript supports definition files that can contain type information of existing JavaScript libraries, much like C++ header files can describe the structure of existing object files. This enables other programs to use the values defined in the files as if they were statically typed TypeScript entities. There are third-party header files for popular libraries such as jQuery, MongoDB, and D3.js. TypeScript headers for the Node.js library modules are also available, allowing development of Node.js programs within TypeScript.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "Official Website",
"url": "https://www.typescriptlang.org/",
"title": "TypeScript Website",
"url": "https://typescriptlang.org/",
"type": "article"
},
{
"title": "The TypeScript Handbook",
"url": "https://www.typescriptlang.org/docs/handbook/intro.html",
"title": "TypeScript Docs",
"url": "https://typescriptlang.org/docs",
"type": "article"
},
{
"title": "Explore top posts about TypeScript",
"url": "https://app.daily.dev/tags/typescript?ref=roadmapsh",
"type": "article"
},
{
"title": "TypeScript for Beginners",
"url": "https://www.youtube.com/watch?v=BwuLxPH8IDs",
"title": "Learn Typescript Basics in 12 Minutes",
"url": "https://www.youtube.com/watch?v=ahCwqrYpIuM&pp=ygULdHlwZXNjcnJpcHQ%3D",
"type": "video"
}
]

View File

@@ -315,6 +315,11 @@
"url": "https://www.tutorialspoint.com/typescript/index.htm",
"type": "article"
},
{
"title": "Scrimba — TypeScript Basics",
"url": "https://scrimba.com/learn/typescript?via=roadmap",
"type": "article"
},
{
"title": "Explore top posts about JavaScript",
"url": "https://app.daily.dev/tags/javascript?ref=roadmapsh",
@@ -1416,24 +1421,8 @@
},
"O7H6dt3Z7EKohxfJzwbPM": {
"title": "Kanban",
"description": "`Kanban` is a popular agile methodology that focuses on visualizing workflow and continuously improving that flow. It's a more flexible approach than Scrum, without the rigid framework.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "What Is Kanban? A Simple Guide to Improve Efficiency.",
"url": "https://businessmap.io/kanban-resources/getting-started/what-is-kanban",
"type": "article"
},
{
"title": "Kanban Methodology: The Simplest Agile Framework ",
"url": "https://kissflow.com/project/agile/kanban-methodology/",
"type": "article"
},
{
"title": "What is Kanban Methodology? The Ultimate Guide",
"url": "https://www.wrike.com/kanban-guide/what-is-kanban/",
"type": "article"
}
]
"description": "",
"links": []
},
"PKqwKvoffm0unwcFwpojk": {
"title": "Scrum",
@@ -1442,24 +1431,8 @@
},
"7fL9lSu4BD1wRjnZy9tM9": {
"title": "XP",
"description": "`Extreme Programming (XP)` is a popular agile software development framework that emphasizes speed, simplicity, and quality. It was developed by Kent Beck in the late 1990s and is based on five values:\n\n* **Communication**: Open and honest communication among team members and stakeholders is essential.\n* **Simplicity**: The simplest solution that works is always preferred.\n* **Feedback**: Continuous feedback from customers and team members is used to improve the product.\n* **Courage**: Team members must be willing to make changes and take risks.\n* **Respect**: Everyone on the team is treated with respect.\n\nVisit the following resources to learn more:",
"links": [
{
"title": "What is Extreme Programming (XP)?",
"url": "https://www.agilealliance.org/glossary/xp/",
"type": "article"
},
{
"title": "It's Values, Principles, And Practices",
"url": "https://www.nimblework.com/agile/extreme-programming-xp/",
"type": "article"
},
{
"title": "Extreme Programming (XP)",
"url": "https://scrum-master.org/en/extreme-programming-xp-a-beginners-guide-to-the-agile-method/",
"type": "article"
}
]
"description": "",
"links": []
},
"cBWJ6Duw99tSKr7U6OW3A": {
"title": "Networks",

File diff suppressed because it is too large Load Diff

View File

@@ -352,7 +352,7 @@
"description": "The lifecycle meta-argument in Terraform customizes the behavior of resources during creation, update, and deletion. It includes settings such as create\\_before\\_destroy, which ensures a new resource is created before the old one is destroyed, preventing downtime. prevent\\_destroy protects resources from accidental deletion, and ignore\\_changes specifies attributes to ignore during updates, allowing external modifications without triggering Terraform changes. These options provide fine-grained control over resource management, ensuring that the desired state of infrastructure is maintained with minimal disruption and precise handling of resource lifecycles.\n\nLearn more from the following resources:",
"links": [
{
"title": "Terraform Docs - lifecycle",
"title": "Terraform Docs - for_each",
"url": "https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle",
"type": "article"
},
@@ -535,7 +535,7 @@
"type": "article"
},
{
"title": "Suppressing values in CLI output",
"title": "Surpressing values in CLI output",
"url": "https://developer.hashicorp.com/terraform/language/values/outputs#sensitive-suppressing-values-in-cli-output",
"type": "article"
}

View File

@@ -9,7 +9,7 @@
"type": "article"
},
{
"title": "TypeScript Official Handbook",
"title": "TypeScript Handbook",
"url": "https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html",
"type": "article"
},
@@ -163,7 +163,7 @@
"description": "The TypeScript Playground is a great tool to learn TypeScript. It allows you to write TypeScript code and see the JavaScript output. It also allows you to share your code with others.\n\nLearn more from the following links:",
"links": [
{
"title": "TypeScript Official - Playground",
"title": "TypeScript - Playground",
"url": "https://www.typescriptlang.org/play",
"type": "article"
},
@@ -349,7 +349,7 @@
"description": "The `never` type represents the type of values that never occur. For instance, `never` is the return type for a function expression or an arrow function expression that always throws an exception or one that never returns. Variables also acquire the type never when narrowed by any type guards that can never be `true`.\n\nThe never type is a subtype of, and assignable to, every type; however, no type is a subtype of, or assignable to, `never` (except `never` itself). Even any isnt assignable to `never`.\n\nExamples of functions returning never:\n\n // Function returning never must not have a reachable end point\n function error(message: string): never {\n throw new Error(message);\n }\n \n // Inferred return type is never\n function fail() {\n return error('Something failed');\n }\n \n // Function returning never must not have a reachable end point\n function infiniteLoop(): never {\n while (true) {}\n }\n \n\nLearn more from the following links:",
"links": [
{
"title": "Never Type",
"title": "Never",
"url": "https://www.typescriptlang.org/docs/handbook/2/narrowing.html#the-never-type",
"type": "article"
}
@@ -379,14 +379,8 @@
},
"afTNr36VqeXoJpHxm2IoS": {
"title": "as any",
"description": "`any` is a special type in TypeScript that represents a value of any type. When a value is declared with the any type, the compiler will not perform any type checks or type inference on that value.\n\nFor example:\n\n let anyValue: any = 42;\n \n // we can assign any value to anyValue, regardless of its type\n anyValue = 'Hello, world!';\n anyValue = true;\n \n\nLearn more from the following links:",
"links": [
{
"title": "Arrays",
"url": "https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any",
"type": "article"
}
]
"description": "`any` is a special type in TypeScript that represents a value of any type. When a value is declared with the any type, the compiler will not perform any type checks or type inference on that value.\n\nFor example:\n\n let anyValue: any = 42;\n \n // we can assign any value to anyValue, regardless of its type\n anyValue = 'Hello, world!';\n anyValue = true;",
"links": []
},
"mjaL5ocLnM8VQlhUxW6KU": {
"title": "Non-null Assertion",
@@ -404,7 +398,7 @@
"description": "TypeScript developers are often faced with a dilemma: we want to ensure that some expression matches some type, but also want to keep the most specific type of that expression for inference purposes.\n\nFor example:\n\n // Each property can be a string or an RGB tuple.\n const palette = {\n red: [255, 0, 0],\n green: '#00ff00',\n bleu: [0, 0, 255],\n // ^^^^ sacrebleu - we've made a typo!\n };\n \n // We want to be able to use array methods on 'red'...\n const redComponent = palette.red.at(0);\n \n // or string methods on 'green'...\n const greenNormalized = palette.green.toUpperCase();\n \n\nNotice that weve written `bleu`, whereas we probably should have written `blue`. We could try to catch that `bleu` typo by using a type annotation on palette, but wed lose the information about each property.\n\n type Colors = 'red' | 'green' | 'blue';\n type RGB = [red: number, green: number, blue: number];\n \n const palette: Record<Colors, string | RGB> = {\n red: [255, 0, 0],\n green: '#00ff00',\n bleu: [0, 0, 255],\n // ~~~~ The typo is now correctly detected\n };\n // But we now have an undesirable error here - 'palette.red' \"could\" be a string.\n const redComponent = palette.red.at(0);\n \n\nThe `satisfies` operator lets us validate that the type of an expression matches some type, without changing the resulting type of that expression. As an example, we could use `satisfies` to validate that all the properties of palette are compatible with `string | number[]`:\n\n type Colors = 'red' | 'green' | 'blue';\n type RGB = [red: number, green: number, blue: number];\n \n const palette = {\n red: [255, 0, 0],\n green: '#00ff00',\n bleu: [0, 0, 255],\n // ~~~~ The typo is now caught!\n } satisfies Record<Colors, string | RGB>;\n \n // Both of these methods are still accessible!\n const redComponent = palette.red.at(0);\n const greenNormalized = palette.green.toUpperCase();\n \n\nLearn more from the following resources:",
"links": [
{
"title": "satisfies Keyword",
"title": "Satisfies Keyword",
"url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html#the-satisfies-operator",
"type": "article"
}
@@ -434,7 +428,7 @@
},
"qefnsugcveizVq2TORRgn": {
"title": "Combining Types",
"description": "In TypeScript, you can combine types using type union and type intersection.\n\nType Union\n----------\n\nThe union operator `|` is used to combine two or more types into a single type that represents all the possible types. For example:\n\n type stringOrNumber = string | number;\n let value: stringOrNumber = 'hello';\n \n value = 42;\n \n\nType Intersection\n-----------------\n\nThe intersection operator `&` is used to intersect two or more types into a single type that represents the properties of all the types. For example:\n\n interface A {\n a: string;\n }\n \n interface B {\n b: number;\n }\n \n type AB = A & B;\n let value: AB = { a: 'hello', b: 42 };\n \n\nLearn more from the following links:",
"description": "In TypeScript, you can combine types using type union and type intersection.\n\n### Type Union:\n\nThe union operator `|` is used to combine two or more types into a single type that represents all the possible types. For example:\n\n type stringOrNumber = string | number;\n let value: stringOrNumber = 'hello';\n \n value = 42;\n \n\n### Type Intersection:\n\nThe intersection operator `&` is used to intersect two or more types into a single type that represents the properties of all the types. For example:\n\n interface A {\n a: string;\n }\n \n interface B {\n b: number;\n }\n \n type AB = A & B;\n let value: AB = { a: 'hello', b: 42 };\n \n\nLearn more from the following links:",
"links": [
{
"title": "Union Types in TypeScript",
@@ -496,7 +490,7 @@
"description": "The `keyof` operator in TypeScript is used to get the union of keys from an object type. Here's an example of how it can be used:\n\n interface User {\n name: string;\n age: number;\n location: string;\n }\n \n type UserKeys = keyof User; // \"name\" | \"age\" | \"location\"\n const key: UserKeys = 'name';\n \n\nIn this example, `UserKeys` is a type that represents the union of keys from the `User` interface, which is `\"name\"` | `\"age\"` | `\"location\"`. And a constant named `key` with the type `UserKeys` is declared with the value `\"name\"`.\n\nLearn more from the following links:",
"links": [
{
"title": "keyof Type Operator",
"title": "Keyof Type Operator",
"url": "https://www.typescriptlang.org/docs/handbook/2/keyof-types.html#handbook-content",
"type": "article"
}
@@ -652,14 +646,8 @@
},
"lvtTSHH9yBTCiLng8btnI": {
"title": "Hybrid Types",
"description": "In TypeScript, a hybrid type is a type that combines multiple types into a single type. The resulting type is considered a union of those types. This allows you to specify that a value can have multiple types, rather than just one.\n\nFor example, you can create a hybrid type that can accept either a string or a number:\n\n type StringOrNumber = string | number;\n \n\nYou can also use hybrid types to create more complex types that can represent a combination of several different types of values. For example:\n\n type Education = {\n degree: string;\n school: string;\n year: number;\n };\n \n type User = {\n name: string;\n age: number;\n email: string;\n education: Education;\n };\n \n\nLearn more from the following links:",
"links": [
{
"title": "Geeksforgeeks.org - Hybrid Types",
"url": "https://www.geeksforgeeks.org/what-are-hybrid-types-in-typescript/#:~:text=Hybrid%20types%20are%20a%20combination,properties%20like%20a%20regular%20object.",
"type": "article"
}
]
"description": "In TypeScript, a hybrid type is a type that combines multiple types into a single type. The resulting type is considered a union of those types. This allows you to specify that a value can have multiple types, rather than just one.\n\nFor example, you can create a hybrid type that can accept either a string or a number:\n\n type StringOrNumber = string | number;\n \n\nYou can also use hybrid types to create more complex types that can represent a combination of several different types of values. For example:\n\n type Education = {\n degree: string;\n school: string;\n year: number;\n };\n \n type User = {\n name: string;\n age: number;\n email: string;\n education: Education;\n };",
"links": []
},
"ib0jfZzukYOZ42AdJqt_W": {
"title": "Classes",
@@ -720,11 +708,6 @@
"title": "Inheritance vs Polymorphism",
"description": "Inheritance and polymorphism are two fundamental concepts in object-oriented programming, and they are supported in TypeScript as well.\n\nInheritance refers to a mechanism where a subclass inherits properties and methods from its parent class. This allows a subclass to reuse the code and behavior of its parent class while also adding or modifying its own behavior. In TypeScript, inheritance is achieved using the extends keyword.\n\nPolymorphism refers to the ability of an object to take on many forms. This allows objects of different classes to be treated as objects of a common class, as long as they share a common interface or inheritance hierarchy. In TypeScript, polymorphism is achieved through method overriding and method overloading.\n\n class Animal {\n makeSound(): void {\n console.log('Making animal sound');\n }\n }\n \n class Dog extends Animal {\n makeSound(): void {\n console.log('Bark');\n }\n }\n \n class Cat extends Animal {\n makeSound(): void {\n console.log('Meow');\n }\n }\n \n let animal: Animal;\n \n animal = new Dog();\n animal.makeSound(); // Output: Bark\n \n animal = new Cat();\n animal.makeSound(); // Output: Meow\n \n\nLearn more from the following resources:",
"links": [
{
"title": "Dev.to - Mastering OOP in TypeScript",
"url": "https://dev.to/rajrathod/mastering-object-oriented-programming-with-typescript-encapsulation-abstraction-inheritance-and-polymorphism-explained-c6p",
"type": "article"
},
{
"title": "Inheritance and Polymorphism In TypeScript",
"url": "https://www.youtube.com/watch?v=Sn6K57YSuwU",
@@ -810,7 +793,7 @@
},
"gBTem9Dp3IQLAkqGX4fOF": {
"title": "Partial",
"description": "The Partial type in TypeScript allows you to make all properties of a type optional. This is useful when you need to create an object with only a subset of the properties of an existing type.\n\nHere's an example of using the Partial type in TypeScript:\n\n interface User {\n name: string;\n age: number;\n email: string;\n }\n \n function createUser(user: Partial<User>): User {\n return {\n name: 'John Doe',\n age: 30,\n email: 'john.doe@example.com',\n ...user,\n };\n }\n \n const newUser = createUser({ name: 'Jane Doe' });\n \n console.log(newUser);\n // Output: { name: 'Jane Doe', age: 30, email: 'john.doe@example.com' }\n \n\nLearn more from the following links:\n\n@official@Partial",
"description": "The Partial type in TypeScript allows you to make all properties of a type optional. This is useful when you need to create an object with only a subset of the properties of an existing type.\n\nHere's an example of using the Partial type in TypeScript:\n\n interface User {\n name: string;\n age: number;\n email: string;\n }\n \n function createUser(user: Partial<User>): User {\n return {\n name: 'John Doe',\n age: 30,\n email: 'john.doe@example.com',\n ...user,\n };\n }\n \n const newUser = createUser({ name: 'Jane Doe' });\n \n console.log(newUser);\n // Output: { name: 'Jane Doe', age: 30, email: 'john.doe@example.com' }\n \n\nLearn more from the following links:\n\n@article@Partial",
"links": []
},
"E88tHQvARkHURZwGaO02l": {
@@ -837,7 +820,7 @@
},
"IuO9-O_DQdDYuAbdGWdgb": {
"title": "Readonly",
"description": "Readonly constructs a type with all properties of Type set to readonly, meaning the properties of the constructed type cannot be reassigned.\n\n interface Todo {\n title: string;\n }\n \n const todo: Readonly<Todo> = {\n title: 'Delete inactive users',\n };\n \n // Cannot assign to 'title' because it is a read-only property.\n todo.title = 'Hello';\n \n\nLearn more from the following links:\n\n@official@Readonly",
"description": "Readonly constructs a type with all properties of Type set to readonly, meaning the properties of the constructed type cannot be reassigned.\n\n interface Todo {\n title: string;\n }\n \n const todo: Readonly<Todo> = {\n title: 'Delete inactive users',\n };\n \n // Cannot assign to 'title' because it is a read-only property.\n todo.title = 'Hello';\n \n\nLearn more from the following links:\n\n@article@Readonly",
"links": []
},
"DRdBmF5Dt_r09LoPOxOuq": {
@@ -875,40 +858,28 @@
},
"_BAZlBEzE7ddr315OeHvl": {
"title": "NonNullable",
"description": "Non-Nullable constructs a type by excluding `null` and `undefined` from Type.\n\n type T0 = NonNullable<string | number | undefined>;\n // type T0 = string | number\n \n type T1 = NonNullable<string[] | null | undefined>;\n // type T1 = string[]\n \n\nLearn more from the following links:\n\n@official@NonNullable",
"description": "Non-Nullable constructs a type by excluding `null` and `undefined` from Type.\n\n type T0 = NonNullable<string | number | undefined>;\n // type T0 = string | number\n \n type T1 = NonNullable<string[] | null | undefined>;\n // type T1 = string[]\n \n\nLearn more from the following links:\n\n@article@NonNullable",
"links": []
},
"a7hl0iMZ-jcUACxqIYVqv": {
"title": "Parameters",
"description": "Parameters constructs a tuple type from the types used in the parameters of a function type Type.\n\n type T0 = Parameters<() => string>;\n // type T0 = []\n \n type T1 = Parameters<(s: string) => void>;\n // type T1 = [s: string]\n \n type T2 = Parameters<<T>(arg: T) => T>;\n // type T2 = [arg: unknown]\n \n declare function f1(arg: { a: number; b: string }): void;\n type T3 = Parameters<typeof f1>;\n // type T3 = [arg: {\n // a: number;\n // b: string;\n // }]\n \n type T4 = Parameters<any>;\n // type T4 = unknown[]\n \n type T5 = Parameters<never>;\n // type T5 = never\n \n type T6 = Parameters<string>;\n // ^ Type 'string' does not satisfy the constraint '(...args: any) => any'.\n \n type T7 = Parameters<Function>;\n // ^ Type 'Function' does not satisfy the constraint '(...args: any) => any'.\n \n\nLearn more from the following links:\n\n@official@Parameters",
"description": "Parameters constructs a tuple type from the types used in the parameters of a function type Type.\n\n type T0 = Parameters<() => string>;\n // type T0 = []\n \n type T1 = Parameters<(s: string) => void>;\n // type T1 = [s: string]\n \n type T2 = Parameters<<T>(arg: T) => T>;\n // type T2 = [arg: unknown]\n \n declare function f1(arg: { a: number; b: string }): void;\n type T3 = Parameters<typeof f1>;\n // type T3 = [arg: {\n // a: number;\n // b: string;\n // }]\n \n type T4 = Parameters<any>;\n // type T4 = unknown[]\n \n type T5 = Parameters<never>;\n // type T5 = never\n \n type T6 = Parameters<string>;\n // ^ Type 'string' does not satisfy the constraint '(...args: any) => any'.\n \n type T7 = Parameters<Function>;\n // ^ Type 'Function' does not satisfy the constraint '(...args: any) => any'.\n \n\nLearn more from the following links:\n\n@article@Parameters",
"links": []
},
"On75JR_UkiIlha0_qaSeu": {
"title": "ReturnType",
"description": "Return type constructs a type consisting of the return type of function Type.\n\n type T0 = ReturnType<() => string>;\n // type T0 = string\n \n type T1 = ReturnType<(s: string) => void>;\n // type T1 = void\n \n type T2 = ReturnType<<T>() => T>;\n // type T2 = unknown\n \n type T3 = ReturnType<<T extends U, U extends number[]>() => T>;\n // type T3 = number[]\n \n declare function f1(): { a: number; b: string };\n type T4 = ReturnType<typeof f1>;\n // type T4 = {\n // a: number;\n // b: string;\n // }\n \n type T5 = ReturnType<any>;\n // type T5 = any\n \n type T6 = ReturnType<never>;\n // type T6 = never\n \n type T7 = ReturnType<string>;\n // ^ Type 'string' does not satisfy the constraint '(...args: any) => any'.\n \n type T8 = ReturnType<Function>;\n // ^ Type 'Function' does not satisfy the constraint '(...args: any) => any'.\n \n\nLearn more from the following links:\n\n@official@ReturnType",
"description": "Return type constructs a type consisting of the return type of function Type.\n\n type T0 = ReturnType<() => string>;\n // type T0 = string\n \n type T1 = ReturnType<(s: string) => void>;\n // type T1 = void\n \n type T2 = ReturnType<<T>() => T>;\n // type T2 = unknown\n \n type T3 = ReturnType<<T extends U, U extends number[]>() => T>;\n // type T3 = number[]\n \n declare function f1(): { a: number; b: string };\n type T4 = ReturnType<typeof f1>;\n // type T4 = {\n // a: number;\n // b: string;\n // }\n \n type T5 = ReturnType<any>;\n // type T5 = any\n \n type T6 = ReturnType<never>;\n // type T6 = never\n \n type T7 = ReturnType<string>;\n // ^ Type 'string' does not satisfy the constraint '(...args: any) => any'.\n \n type T8 = ReturnType<Function>;\n // ^ Type 'Function' does not satisfy the constraint '(...args: any) => any'.\n \n\nLearn more from the following links:\n\n@article@ReturnType",
"links": []
},
"izGAjNtrh3BzQt3KiZX0W": {
"title": "InstanceType",
"description": "This type constructs a type consisting of the instance type of a constructor function in Type.\n\n class C {\n x = 0;\n y = 0;\n }\n \n type T0 = InstanceType<typeof C>;\n // type T0 = C\n \n type T1 = InstanceType<any>;\n // type T1 = any\n \n type T2 = InstanceType<never>;\n // type T2 = never\n \n type T3 = InstanceType<string>;\n // ^ Type 'string' does not satisfy the constraint 'abstract new (...args: any) => any'.\n \n type T4 = InstanceType<Function>;\n // ^ Type 'Function' does not satisfy the constraint 'abstract new (...args: any) => any'.\n \n\nLearn more from the following links:",
"links": [
{
"title": "InstanceType<Type>",
"url": "https://www.typescriptlang.org/docs/handbook/utility-types.html#instancetypetype",
"type": "article"
}
]
"description": "This type constructs a type consisting of the instance type of a constructor function in Type.\n\n class C {\n x = 0;\n y = 0;\n }\n \n type T0 = InstanceType<typeof C>;\n // type T0 = C\n \n type T1 = InstanceType<any>;\n // type T1 = any\n \n type T2 = InstanceType<never>;\n // type T2 = never\n \n type T3 = InstanceType<string>;\n // ^ Type 'string' does not satisfy the constraint 'abstract new (...args: any) => any'.\n \n type T4 = InstanceType<Function>;\n // ^ Type 'Function' does not satisfy the constraint 'abstract new (...args: any) => any'.\n \n\nLearn more from the following links:\n\n@article@InstanceType",
"links": []
},
"aEhI_9mFWXRIZh1ZxTuzu": {
"title": "Awaited",
"description": "This type is meant to model operations like await in async functions, or the `.then()` method on Promises - specifically, the way that they recursively unwrap Promises.\n\n type A = Awaited<Promise<string>>;\n // type A = string\n \n type B = Awaited<Promise<Promise<number>>>;\n // type B = number\n \n type C = Awaited<boolean | Promise<number>>;\n // type C = number | boolean\n \n\nLearn more from the following links:",
"links": [
{
"title": "Awaited<Type>",
"url": "https://www.typescriptlang.org/docs/handbook/utility-types.html#awaitedtype",
"type": "article"
}
]
"description": "This type is meant to model operations like await in async functions, or the `.then()` method on Promises - specifically, the way that they recursively unwrap Promises.\n\n type A = Awaited<Promise<string>>;\n // type A = string\n \n type B = Awaited<Promise<Promise<number>>>;\n // type B = number\n \n type C = Awaited<boolean | Promise<number>>;\n // type C = number | boolean\n \n\nLearn more from the following links:\n\n@article@Awaited",
"links": []
},
"2F7vOL__v9dLBohA263aj": {
"title": "Advanced Types",
@@ -977,14 +948,8 @@
},
"N8xBTJ74xv1E5hSLYZtze": {
"title": "Recursive Types",
"description": "Recursive types in TypeScript are a way to define a type that references itself. Recursive types are used to define complex data structures, such as trees or linked lists, where a value can contain one or more values of the same type.\n\nFor example, the following is a recursive type that represents a linked list:\n\n type LinkedList<T> = {\n value: T;\n next: LinkedList<T> | null;\n };\n \n let list: LinkedList<number> = {\n value: 1,\n next: { value: 2, next: { value: 3, next: null } },\n };\n \n\nIn this example, the `LinkedList` type is defined as a type that extends `T` and contains a property `next` of the same type `LinkedList<T>`. This allows us to create a linked list where each node contains a value of type `T` and a reference to the next node in the list.\n\nLearn more from the following links:",
"links": [
{
"title": "Recursive Types in TypeScript",
"url": "https://www.typescriptlang.org/play/3-7/types-and-code-flow/recursive-type-references.ts.html",
"type": "article"
}
]
"description": "Recursive types in TypeScript are a way to define a type that references itself. Recursive types are used to define complex data structures, such as trees or linked lists, where a value can contain one or more values of the same type.\n\nFor example, the following is a recursive type that represents a linked list:\n\n type LinkedList<T> = {\n value: T;\n next: LinkedList<T> | null;\n };\n \n let list: LinkedList<number> = {\n value: 1,\n next: { value: 2, next: { value: 3, next: null } },\n };\n \n\nIn this example, the `LinkedList` type is defined as a type that extends `T` and contains a property `next` of the same type `LinkedList<T>`. This allows us to create a linked list where each node contains a value of type `T` and a reference to the next node in the list.",
"links": []
},
"sE9lqkkqwnsVJxTJv37YZ": {
"title": "TypeScript Modules",

View File

@@ -36,7 +36,7 @@ Here is the list of available roadmaps with more being actively worked upon.
- [Backend Roadmap](https://roadmap.sh/backend) / [Backend Beginner Roadmap](https://roadmap.sh/backend?r=backend-beginner)
- [DevOps Roadmap](https://roadmap.sh/devops) / [DevOps Beginner Roadmap](https://roadmap.sh/devops?r=devops-beginner)
- [Full Stack Roadmap](https://roadmap.sh/full-stack)
- [Git and GitHub](https://roadmap.sh/git-github)
- [Git and GitHub Roadmap](https://roadmap.sh/git-github)
- [API Design Roadmap](https://roadmap.sh/api-design)
- [Computer Science Roadmap](https://roadmap.sh/computer-science)
- [Data Structures and Algorithms Roadmap](https://roadmap.sh/datastructures-and-algorithms)

View File

@@ -1,15 +0,0 @@
import { type APIContext } from 'astro';
import { api } from './api.ts';
export function projectApi(context: APIContext) {
return {
listProjectsUserCount: async function (projectIds: string[]) {
return api(context).post<Record<string, number>>(
`${import.meta.env.PUBLIC_API_URL}/v1-list-projects-user-count`,
{
projectIds,
},
);
},
};
}

View File

@@ -5,6 +5,10 @@ import { ResourceProgress } from './ResourceProgress';
import { pageProgressMessage } from '../../stores/page';
import { EmptyActivity } from './EmptyActivity';
import { ActivityStream, type UserStreamActivity } from './ActivityStream';
import type { ProjectStatusDocument } from '../Projects/ListProjectSolutions';
import type { PageType } from '../CommandMenu/CommandMenu';
import { useToast } from '../../hooks/use-toast';
import { ProjectProgress } from './ProjectProgress';
type ProgressResponse = {
updatedAt: string;
@@ -47,11 +51,14 @@ export type ActivityResponse = {
};
}[];
activities: UserStreamActivity[];
projects: ProjectStatusDocument[];
};
export function ActivityPage() {
const toast = useToast();
const [activity, setActivity] = useState<ActivityResponse>();
const [isLoading, setIsLoading] = useState(true);
const [projectDetails, setProjectDetails] = useState<PageType[]>([]);
async function loadActivity() {
const { error, response } = await httpGet<ActivityResponse>(
@@ -68,11 +75,30 @@ export function ActivityPage() {
setActivity(response);
}
async function loadAllProjectDetails() {
const { error, response } = await httpGet<PageType[]>(`/pages.json`);
if (error) {
toast.error(error.message || 'Something went wrong');
return;
}
if (!response) {
return [];
}
const allProjects = response.filter((page) => page.group === 'Projects');
console.log(allProjects);
setProjectDetails(allProjects);
}
useEffect(() => {
loadActivity().finally(() => {
pageProgressMessage.set('');
setIsLoading(false);
});
Promise.allSettled([loadActivity(), loadAllProjectDetails()]).finally(
() => {
pageProgressMessage.set('');
setIsLoading(false);
},
);
}, []);
const learningRoadmaps = activity?.learning.roadmaps || [];
@@ -106,6 +132,17 @@ export function ActivityPage() {
learningRoadmapsToShow.length !== 0 ||
learningBestPracticesToShow.length !== 0;
const enrichedProjects = activity?.projects.map((project) => {
const projectDetail = projectDetails.find(
(page) => page.id === project.projectId,
);
return {
...project,
title: projectDetail?.title || 'N/A',
};
});
return (
<>
<ActivityCounters
@@ -201,6 +238,19 @@ export function ActivityPage() {
)}
</div>
{enrichedProjects && enrichedProjects?.length > 0 && (
<div className="mx-0 px-0 py-5 pb-0 md:-mx-10 md:px-8 md:py-8 md:pb-0">
<h2 className="mb-3 text-xs uppercase text-gray-400">
Your Projects
</h2>
<div className="grid grid-cols-1 gap-1.5 sm:grid-cols-2">
{enrichedProjects.map((project) => (
<ProjectProgress key={project._id} projectStatus={project} />
))}
</div>
</div>
)}
{hasProgress && (
<ActivityStream activities={activity?.activities || []} />
)}

View File

@@ -0,0 +1,50 @@
import { getUser } from '../../lib/jwt';
import { getPercentage } from '../../helper/number';
import { ProjectProgressActions } from './ProjectProgressActions';
import { cn } from '../../lib/classname';
import type { ProjectStatusDocument } from '../Projects/ListProjectSolutions';
import { ProjectStatus } from './ProjectStatus';
import { ThumbsUp } from 'lucide-react';
type ProjectProgressType = {
projectStatus: ProjectStatusDocument & {
title: string;
};
};
export function ProjectProgress(props: ProjectProgressType) {
const { projectStatus } = props;
const userId = getUser()?.id;
const shouldShowActions =
projectStatus.submittedAt && projectStatus.submittedAt !== null;
return (
<div className="relative">
<a
className={cn(
'group relative flex w-full items-center justify-between overflow-hidden rounded-md border border-gray-300 bg-white px-3 py-2 pr-7 text-left text-sm transition-all hover:border-gray-400',
shouldShowActions ? '' : 'pr-3',
)}
href={`/projects/${projectStatus.projectId}`}
target="_blank"
>
<ProjectStatus projectStatus={projectStatus} />
<span className="ml-2 flex-grow truncate">{projectStatus?.title}</span>
<span className="inline-flex items-center gap-1 text-xs text-gray-400">
{projectStatus.upvotes}
<ThumbsUp className="size-2.5 stroke-[2.5px]" />
</span>
</a>
{shouldShowActions && (
<div className="absolute right-2 top-0 flex h-full items-center">
<ProjectProgressActions
userId={userId!}
projectId={projectStatus.projectId}
/>
</div>
)}
</div>
);
}

View File

@@ -0,0 +1,68 @@
import { MoreVertical, X } from 'lucide-react';
import { useRef, useState } from 'react';
import { useOutsideClick } from '../../hooks/use-outside-click';
import { useKeydown } from '../../hooks/use-keydown';
import { cn } from '../../lib/classname';
import { useCopyText } from '../../hooks/use-copy-text';
import { CheckIcon } from '../ReactIcons/CheckIcon';
import { ShareIcon } from '../ReactIcons/ShareIcon';
type ProjectProgressActionsType = {
userId: string;
projectId: string;
};
export function ProjectProgressActions(props: ProjectProgressActionsType) {
const { userId, projectId } = props;
const dropdownRef = useRef<HTMLDivElement>(null);
const [isOpen, setIsOpen] = useState(false);
const { copyText, isCopied } = useCopyText();
const projectSolutionUrl = `${import.meta.env.DEV ? 'http://localhost:3000' : 'https://roadmap.sh'}/projects/${projectId}/solutions?u=${userId}`;
useOutsideClick(dropdownRef, () => {
setIsOpen(false);
});
useKeydown('Escape', () => {
setIsOpen(false);
});
return (
<div className="relative h-full" ref={dropdownRef}>
<button
className="h-full text-gray-400 hover:text-gray-700"
onClick={() => setIsOpen(!isOpen)}
>
<MoreVertical size={16} />
</button>
{isOpen && (
<div className="absolute right-0 top-8 z-10 w-48 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg">
<button
className={cn(
'flex w-full items-center gap-1.5 p-2 text-xs font-medium hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-70 sm:text-sm',
isCopied ? 'text-green-500' : 'text-gray-500 hover:text-black',
)}
onClick={() => {
copyText(projectSolutionUrl);
}}
>
{isCopied ? (
<>
<CheckIcon additionalClasses="h-3.5 w-3.5" /> Link Copied
</>
) : (
<>
<ShareIcon className="h-3.5 w-3.5 stroke-[2.5px]" /> Share
Solution
</>
)}
</button>
</div>
)}
</div>
);
}

View File

@@ -0,0 +1,24 @@
import { CircleDashed } from 'lucide-react';
import type { ProjectStatusDocument } from '../Projects/ListProjectSolutions';
import { CheckIcon } from '../ReactIcons/CheckIcon';
type ProjectStatusType = {
projectStatus: ProjectStatusDocument & {
title: string;
};
};
export function ProjectStatus(props: ProjectStatusType) {
const { projectStatus } = props;
const { submittedAt, repositoryUrl } = projectStatus;
const status = submittedAt && repositoryUrl ? 'submitted' : 'started';
if (status === 'submitted') {
return <CheckIcon additionalClasses="size-3 text-gray-500 shrink-0" />;
}
return (
<CircleDashed className="size-3 shrink-0 stroke-[2.5px] text-gray-400" />
);
}

View File

@@ -1,227 +0,0 @@
import React, { useState } from 'react';
import { CheckIcon } from './ReactIcons/CheckIcon.tsx';
import { pageProgressMessage } from '../stores/page.ts';
import { httpPost } from '../lib/http.ts';
type InputProps = {
label: string;
name: string;
type: string;
value: string;
onChange: (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => void;
required?: boolean;
rows?: number;
};
function Input(props: InputProps) {
const { label, name, type, value, onChange, required, rows } = props;
return (
<div className="mb-4">
<label htmlFor={name} className="block text-sm font-medium text-gray-700">
{label} {required && <span className="text-red-500">*</span>}
</label>
{type === 'textarea' ? (
<textarea
placeholder={label}
id={name}
name={name}
value={value}
onChange={onChange}
rows={rows}
className="mt-1 block w-full rounded-md border border-gray-300 p-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
autoComplete="off"
data-1p-ignore=""
data-form-type="other"
data-lpignore="true"
></textarea>
) : (
<input
type={type}
id={name}
placeholder={label}
name={name}
value={value}
onChange={onChange}
required={required}
className="mt-1 block w-full rounded-md border border-gray-300 p-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
autoComplete="off"
data-1p-ignore=""
data-form-type="other"
data-lpignore="true"
/>
)}
</div>
);
}
export function AdvertiseForm() {
const [status, setStatus] = useState<'submitting' | 'submitted'>();
const [error, setError] = useState<string | null>(null);
const [formData, setFormData] = useState({
firstName: '',
lastName: '',
title: '',
company: '',
email: '',
phone: '',
message: '',
updates: false,
});
const handleInputChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
const { name, value, type, checked } = e.target as any;
setFormData({
...formData,
[name]: type === 'checkbox' ? checked : value,
});
};
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
pageProgressMessage.set('Please wait');
// Placeholder function to send data
console.log('Form data:', formData);
const { response, error } = await httpPost(
`${import.meta.env.PUBLIC_API_URL}/v1-advertise`,
formData,
);
if (!response || error) {
pageProgressMessage.set('');
setError(error?.message || 'Something went wrong. Please try again.');
return;
}
setStatus('submitted');
pageProgressMessage.set('');
}
if (status === 'submitted') {
return (
<div className="flex flex-col items-center justify-center rounded-md border bg-gray-50 p-12 text-center">
<CheckIcon additionalClasses="h-12 w-12 text-green-500 mb-5" />
<h2 className="text-balance text-xl font-semibold text-gray-900">
Thank you for your interest in advertising with roadmap.sh
</h2>
<p className="mt-2 text-sm text-gray-500">
We will get back to you soon.
</p>
</div>
);
}
return (
<>
<h2 className="mb-5 text-balance text-2xl font-bold">
Ready to learn more? Fill out the form below to get started!
</h2>
{error && (
<div className="relative mb-4 rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700">
{error}
</div>
)}
<form className="mb-5" onSubmit={handleSubmit}>
<div className="grid gap-0 sm:grid-cols-2 sm:gap-4">
<Input
label="First Name"
name="firstName"
type="text"
value={formData.firstName}
onChange={handleInputChange}
required
/>
<Input
label="Last Name"
name="lastName"
type="text"
value={formData.lastName}
onChange={handleInputChange}
required
/>
</div>
<div className="grid gap-0 sm:grid-cols-2 sm:gap-4">
<Input
label="Title"
name="title"
type="text"
value={formData.title}
onChange={handleInputChange}
required
/>
<Input
label="Company"
name="company"
type="text"
value={formData.company}
onChange={handleInputChange}
required
/>
</div>
<div className="grid gap-0 sm:grid-cols-2 sm:gap-4">
<Input
label="Email"
name="email"
type="email"
value={formData.email}
onChange={handleInputChange}
required
/>
<Input
label="Phone"
name="phone"
type="tel"
value={formData.phone}
onChange={handleInputChange}
/>
</div>
<Input
label="Message (Optional)"
name="message"
type="textarea"
value={formData.message}
onChange={handleInputChange}
rows={4}
/>
<div className="mb-4 flex items-start">
<div className="flex h-5 items-center">
<input
id="updates"
name="updates"
type="checkbox"
checked={formData.updates}
onChange={handleInputChange}
className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
/>
</div>
<div className="ml-3 text-sm">
<label htmlFor="updates" className="font-medium text-gray-700">
I want to receive occasional updates about new products or
advertising opportunities with roadmap.sh
</label>
</div>
</div>
<div>
<button
type="submit"
className="flex justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
Send
</button>
</div>
</form>
</>
);
}

View File

@@ -59,7 +59,6 @@ export function EmailLoginForm(props: EmailLoginFormProps) {
Email address
</label>
<input
id="email"
name="email"
type="email"
autoComplete="email"
@@ -73,7 +72,6 @@ export function EmailLoginForm(props: EmailLoginFormProps) {
Password
</label>
<input
id="password"
name="password"
type="password"
autoComplete="current-password"

View File

@@ -122,7 +122,6 @@ export function CustomRoadmap(props: CustomRoadmapProps) {
{!isEmbed && <RoadmapHeader />}
<FlowRoadmapRenderer isEmbed={isEmbed} roadmap={roadmap!} />
<TopicDetail
resourceId={roadmap!._id}
resourceTitle={roadmap!.title}
resourceType="roadmap"
isEmbed={isEmbed}

View File

@@ -35,8 +35,8 @@ import Icon from './AstroIcon.astro';
>
</p>
<div class='flex flex-col justify-between gap-8 lg:gap-2 lg:flex-row'>
<div class='max-w-[425px]'>
<div class='flex flex-col justify-between gap-12 sm:flex-row'>
<div class='max-w-[365px]'>
<p class='text-md flex items-center'>
<a
class='inline-flex items-center text-lg font-medium text-white transition-colors hover:text-gray-400'
@@ -56,7 +56,7 @@ import Icon from './AstroIcon.astro';
</a>
</p>
<p class='my-4 text-slate-300/60'>
Community created roadmaps, best practices, projects, articles, resources and journeys to help
Community created roadmaps, articles, resources and journeys to help
you choose your path and grow in your career.
</p>
<div class='text-sm text-gray-400'>
@@ -67,8 +67,6 @@ import Icon from './AstroIcon.astro';
<span class='mx-1.5'>&middot;</span>
<a href='/privacy' class='hover:text-white'>Privacy</a>
<span class='mx-1.5'>&middot;</span>
<a href='/advertise' class='hover:text-white'>Advertise</a>
<span class='mx-1.5'>&middot;</span>
<a
aria-label='Write us an email'
href='mailto:info@roadmap.sh'
@@ -99,19 +97,20 @@ import Icon from './AstroIcon.astro';
</div>
</div>
<div class='max-w-[340px] text-left lg:text-right'>
<div class='max-w-[365px] text-left sm:text-right'>
<a href='https://thenewstack.io' target='_blank'>
<img
src='/images/tns-sm.png'
alt='ThewNewStack'
class='my-1.5 mr-auto lg:ml-auto lg:mr-0'
class='my-1.5 mr-auto sm:ml-auto sm:mr-0'
width='200'
height='24.8'
loading="lazy"
/>
</a>
<p class='my-4 text-slate-300/60'>
The top DevOps resource for Kubernetes, cloud-native computing, and large-scale development and deployment.
The leading DevOps resource for Kubernetes, cloud-native computing,
and the latest in at-scale development, deployment, and management.
</p>
<div class='text-sm text-gray-400'>
<p>

View File

@@ -62,12 +62,6 @@ const links = [
Icon: Shirt,
isExternal: true,
},
{
link: '/advertise',
label: 'Advertise',
description: 'Promote your product or service',
Icon: Menu,
},
];
export function NavigationDropdown() {

View File

@@ -33,7 +33,7 @@ export interface ProjectStatusDocument {
isVisible?: boolean;
updated1t: Date;
updatedAt: Date;
}
const allowedVoteType = ['upvote', 'downvote'] as const;

View File

@@ -3,12 +3,9 @@ import type {
ProjectDifficultyType,
ProjectFileType,
} from '../../lib/project.ts';
import { Users } from 'lucide-react';
import { formatCommaNumber } from '../../lib/number.ts';
type ProjectCardProps = {
project: ProjectFileType;
userCount?: number;
};
const badgeVariants: Record<ProjectDifficultyType, string> = {
@@ -18,7 +15,7 @@ const badgeVariants: Record<ProjectDifficultyType, string> = {
};
export function ProjectCard(props: ProjectCardProps) {
const { project, userCount = 0 } = props;
const { project } = props;
const { frontmatter, id } = project;
@@ -34,18 +31,8 @@ export function ProjectCard(props: ProjectCardProps) {
/>
<Badge variant={'grey'} text={frontmatter.nature} />
</span>
<span className="my-3 flex flex-col">
<span className="mb-1 font-medium">{frontmatter.title}</span>
<span className="text-sm text-gray-500">{frontmatter.description}</span>
</span>
<span className="flex items-center gap-2 text-xs text-gray-400">
<Users className="inline-block size-3.5" />
{userCount > 0 ? (
<>{formatCommaNumber(userCount)} Started</>
) : (
<>Be the first to solve!</>
)}
</span>
<span className="mb-1 mt-2.5 font-medium">{frontmatter.title}</span>
<span className="text-sm text-gray-500">{frontmatter.description}</span>
</a>
);
}

View File

@@ -8,7 +8,7 @@ import {
type AllowedVoteType,
} from './ListProjectSolutions';
import { getRelativeTimeString } from '../../lib/date';
import { ArrowUpRight, ThumbsDown, ThumbsUp, Trophy } from 'lucide-react';
import { ArrowUpRight, ThumbsDown, ThumbsUp } from 'lucide-react';
import { VoteButton } from './VoteButton';
import { GitHubIcon } from '../ReactIcons/GitHubIcon';
import { isLoggedIn } from '../../lib/jwt';
@@ -131,58 +131,64 @@ export function ProjectSolutionModal(props: ProjectSolutionModalProps) {
deleteUrlParam('u');
window.location.reload();
}}
wrapperClassName={'max-w-lg'}
bodyClassName={'h-auto'}
>
<div className="relative p-6">
<h1 className="text-2xl text-balance mb-1 font-bold text-gray-900">{projectTitle}</h1>
<p className="text-sm text-balance text-gray-600">{projectDescription}</p>
<div className="relative p-4">
<h1 className="text-xl font-semibold">{projectTitle}</h1>
<p className="mt-1 max-w-xs text-sm text-gray-500">
{projectDescription}
</p>
<div className="my-5 rounded-lg bg-gray-100 p-4">
<div className="flex items-center gap-3">
<img
src={
avatar
? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${avatar}`
: '/images/default-avatar.png'
}
alt={solution?.user?.name}
className="h-12 w-12 rounded-full border-2 border-white shadow-md"
/>
<div>
<h2 className="text-lg font-semibold text-gray-900">{solution?.user.name}'s Solution</h2>
<p className="text-sm text-gray-600">
Submitted their solution{' '}
{getRelativeTimeString(solution?.submittedAt!)}
</p>
</div>
</div>
<hr className="-mx-4 my-4 border-gray-300" />
<div className="flex items-center gap-1.5">
<img
src={
avatar
? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${avatar}`
: '/images/default-avatar.png'
}
alt={solution?.user?.name}
className="mr-0.5 h-7 w-7 rounded-full"
/>
<span className="font-medium text-black">{solution?.user.name}</span>
<span className="hidden sm:inline">
{submittedAlternatives[
Math.floor(Math.random() * submittedAlternatives.length)
] || 'submitted their solution'}
</span>{' '}
<span className="flex-grow text-right text-gray-400 sm:flex-grow-0 sm:text-left sm:font-medium sm:text-black">
{getRelativeTimeString(solution?.submittedAt!)}
</span>
</div>
<div className="flex items-center justify-between">
<div className="mt-4 flex items-center justify-between gap-2">
<a
className="flex items-center gap-2 rounded-full bg-black px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-gray-800"
className="flex items-center gap-1 rounded-full border px-2 py-1 text-xs text-black transition-colors hover:border-black hover:bg-black hover:text-white"
href={solution?.repositoryUrl}
target="_blank"
>
<GitHubIcon className="h-5 w-5 text-current" />
View Solution on GitHub
<ArrowUpRight className="h-4 w-4" />
<GitHubIcon className="h-4 w-4 text-current" />
View Solution
</a>
<div className="flex overflow-hidden rounded-full border">
<div className="flex shrink-0 overflow-hidden rounded-full border">
<VoteButton
icon={ThumbsUp}
isActive={solution?.voteType === 'upvote'}
count={solution?.upvotes || 0}
onClick={() => handleSubmitVote(solution?.id!, 'upvote')}
onClick={() => {
handleSubmitVote(solution?.id!, 'upvote');
}}
/>
<VoteButton
icon={ThumbsDown}
isActive={solution?.voteType === 'downvote'}
count={solution?.downvotes || 0}
hideCount={true}
onClick={() => handleSubmitVote(solution?.id!, 'downvote')}
onClick={() => {
handleSubmitVote(solution?.id!, 'downvote');
}}
/>
</div>
</div>

View File

@@ -40,11 +40,10 @@ function DifficultyButton(props: DifficultyButtonProps) {
type ProjectsListProps = {
projects: ProjectFileType[];
userCounts: Record<string, number>;
};
export function ProjectsList(props: ProjectsListProps) {
const { projects, userCounts } = props;
const { projects } = props;
const { difficulty: urlDifficulty } = getUrlParams();
const [difficulty, setDifficulty] = useState<
@@ -128,10 +127,9 @@ export function ProjectsList(props: ProjectsListProps) {
.sort((a, b) => {
return a.frontmatter.sort - b.frontmatter.sort;
})
.map((matchingProject) => {
const count = userCounts[matchingProject?.id] || 0;
return <ProjectCard project={matchingProject} userCount={count} />;
})}
.map((matchingProject) => (
<ProjectCard project={matchingProject} />
))}
</div>
</div>
);

View File

@@ -207,7 +207,7 @@ export function ProjectStepper(props: ProjectStepperProps) {
) : (
<>
<Share className="h-3 w-3 stroke-[2.5px]" />
<span className="hidden md:inline">Share your Solution</span>
<span className="hidden md:inline">Share Solution</span>
<span className="md:hidden">Share</span>
</>
)}
@@ -262,12 +262,12 @@ export function ProjectStepper(props: ProjectStepperProps) {
{isCopied ? (
<>
<CheckIcon additionalClasses="h-3 w-3" />
URL Copied
Copied
</>
) : (
<>
<Share className="h-3 w-3 stroke-[2.5px]" />
Share your Solution
Share Solution
</>
)}
</button>

View File

@@ -1,4 +1,5 @@
import { CheckIcon, CopyIcon, X } from 'lucide-react';
import { CheckIcon as ReactCheckIcon } from '../ReactIcons/CheckIcon.tsx';
import { Modal } from '../Modal';
import { type FormEvent, useState } from 'react';
import { httpPost } from '../../lib/http';
@@ -39,7 +40,7 @@ export function SubmitProjectModal(props: SubmitProjectModalProps) {
const { isCopied, copyText } = useCopyText();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState('');
const [isSuccess, setIsSuccess] = useState(false);
const [successMessage, setSuccessMessage] = useState('');
const [repoUrl, setRepoUrl] = useState(defaultRepositoryUrl);
const [verificationChecks, setVerificationChecks] =
useState<VerificationChecksType>({
@@ -61,7 +62,7 @@ export function SubmitProjectModal(props: SubmitProjectModalProps) {
setIsLoading(true);
setError('');
setIsSuccess(false);
setSuccessMessage('');
if (!repoUrl) {
setVerificationChecks({
@@ -198,7 +199,7 @@ export function SubmitProjectModal(props: SubmitProjectModalProps) {
);
}
setIsSuccess(true);
setSuccessMessage('Solution submitted successfully!');
setIsLoading(false);
onSubmit(submitResponse);
@@ -209,8 +210,14 @@ export function SubmitProjectModal(props: SubmitProjectModalProps) {
}
};
if (isSuccess) {
return <SubmitSuccessModal projectId={projectId} onClose={onClose} />;
if (successMessage) {
return (
<SubmitSuccessModal
projectId={projectId}
onClose={onClose}
successMessage={successMessage}
/>
);
}
return (
@@ -289,6 +296,12 @@ export function SubmitProjectModal(props: SubmitProjectModalProps) {
{error && (
<p className="mt-2 text-sm font-medium text-red-500">{error}</p>
)}
{successMessage && (
<p className="mt-2 text-sm font-medium text-green-500">
{successMessage}
</p>
)}
</form>
<button

View File

@@ -1,4 +1,10 @@
import { CheckCircle, CheckCircle2, Clipboard, Copy } from 'lucide-react';
import {
CheckCircle2,
Clipboard,
Facebook,
Linkedin,
Twitter,
} from 'lucide-react';
import { getUser } from '../../lib/jwt.ts';
import { Modal } from '../Modal';
import { CheckIcon as ReactCheckIcon } from '../ReactIcons/CheckIcon.tsx';
@@ -8,43 +14,62 @@ import { cn } from '../../lib/classname.ts';
type SubmitSuccessModalProps = {
projectId: string;
onClose: () => void;
successMessage: string;
};
export function SubmitSuccessModal(props: SubmitSuccessModalProps) {
const { onClose, projectId } = props;
const { onClose, successMessage, projectId } = props;
const user = getUser();
const description = 'Check out my solution to this project on Roadmap.sh';
const projectSolutionUrl = `${import.meta.env.DEV ? 'http://localhost:3000' : 'https://roadmap.sh'}/projects/${projectId}/solutions?u=${user?.id}`;
const { isCopied, copyText } = useCopyText();
const socialShareLinks = [
{
title: 'Twitter',
href: `https://x.com/intent/tweet?text=${description}&url=${projectSolutionUrl}`,
icon: <Twitter className="size-4 text-gray-700" />,
},
{
title: 'Facebook',
href: `https://www.facebook.com/sharer/sharer.php?quote=${description}&u=${projectSolutionUrl}`,
icon: <Facebook className="size-4 text-gray-700" />,
},
{
title: 'Linkedin',
href: `https://www.linkedin.com/sharing/share-offsite/?url=${projectSolutionUrl}`,
icon: <Linkedin className="size-4 text-gray-700" />,
},
];
return (
<Modal onClose={onClose} bodyClassName="h-auto p-4">
<div className="flex flex-col items-center justify-center pb-3 pt-12">
<div className="flex flex-col items-center justify-center pb-5 pt-12">
<ReactCheckIcon additionalClasses="h-12 text-green-500 w-12" />
<p className="mt-4 text-lg font-medium">Solution Submitted</p>
<p className="mt-4 text-lg font-medium">{successMessage}</p>
<p className="mt-0.5 text-center text-sm text-gray-500">
Congrats! Your solution has been submitted.
You can use the link to share your solution with others.
</p>
<div className="mt-4 w-full">
<div className="mt-4 flex w-full items-stretch rounded-md border bg-gray-50">
<input
type="text"
readOnly={true}
value={projectSolutionUrl}
className="w-full rounded-md border bg-gray-50 px-2.5 py-2 text-sm text-gray-700 focus:outline-none"
className="w-full bg-transparent px-2.5 py-2 text-sm text-gray-700 focus:outline-none"
onClick={(e) => {
e.currentTarget.select();
copyText(projectSolutionUrl);
}}
/>
<button
className={cn(
'mt-2 flex w-full items-center justify-center gap-1 rounded-md px-2 py-2 text-sm font-medium transition-colors',
isCopied
? 'bg-green-600 text-white hover:bg-green-700'
: 'bg-black text-white hover:bg-gray-800'
'm-1 ml-0 flex items-center gap-1 rounded-md bg-gray-200 px-2 py-1.5 text-xs font-medium text-black',
isCopied ? 'bg-green-200 text-green-900' : '',
)}
onClick={() => {
copyText(projectSolutionUrl);
@@ -52,17 +77,35 @@ export function SubmitSuccessModal(props: SubmitSuccessModalProps) {
>
{isCopied ? (
<>
<CheckCircle className="size-4 stroke-[2.5px]" />
URL Copied
<CheckCircle2 className="size-3 stroke-[2.5px]" />
Copied
</>
) : (
<>
<Copy className="size-4 stroke-[2.5px]" />
Copy Shareable Link
<Clipboard className="size-3 stroke-[2.5px]" />
Copy
</>
)}
</button>
</div>
<div className="mt-8 flex justify-center gap-2">
{socialShareLinks.map((socialLink) => (
<a
key={socialLink.title}
href={socialLink.href}
target="_blank"
rel="noreferrer"
className="flex h-7 w-7 shrink-0 items-center justify-center rounded-md border bg-gray-50 hover:bg-gray-100"
>
{socialLink.icon}
</a>
))}
</div>
<p className="mt-4 text-sm text-gray-500">
Share your solution with the others!
</p>
</div>
</Modal>
);

View File

@@ -1,17 +0,0 @@
interface FacebookIconProps {
className?: string;
}
export function FacebookIcon(props: FacebookIconProps) {
const { className } = props;
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512"
fill="currentColor"
className={className}
>
<path d="M400 32H48A48 48 0 0 0 0 80v352a48 48 0 0 0 48 48h137.25V327.69h-63V256h63v-54.64c0-62.15 37-96.48 93.67-96.48 27.14 0 55.52 4.84 55.52 4.84v61h-31.27c-30.81 0-40.42 19.12-40.42 38.73V256h68.78l-11 71.69h-57.78V480H400a48 48 0 0 0 48-48V80a48 48 0 0 0-48-48z" />
</svg>
);
}

View File

@@ -1,29 +1,49 @@
interface LinkedInIconProps {
type LinkedInIconProps = {
className?: string;
}
};
export function LinkedInIcon(props: LinkedInIconProps) {
const { className } = props;
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
x="0px"
y="0px"
width="100"
height="100"
viewBox="0,0,256,256"
>
<g clipPath="url(#clip0_2344_20)">
<path
d="M0 0V24H24V0H0ZM8 19H5V8H8V19ZM6.5 6.732C5.534 6.732 4.75 5.942 4.75 4.968C4.75 3.994 5.534 3.204 6.5 3.204C7.466 3.204 8.25 3.994 8.25 4.968C8.25 5.942 7.467 6.732 6.5 6.732ZM20 19H17V13.396C17 10.028 13 10.283 13 13.396V19H10V8H13V9.765C14.397 7.179 20 6.988 20 12.241V19Z"
fill="currentColor"
/>
<g transform="translate(-26.66667,-26.66667) scale(1.20833,1.20833)">
<g
fill="none"
fillRule="nonzero"
stroke="none"
strokeWidth="1"
strokeLinecap="butt"
strokeLinejoin="miter"
strokeMiterlimit="10"
strokeDasharray=""
strokeDashoffset="0"
fontFamily="none"
fontWeight="none"
fontSize="none"
textAnchor="none"
style={{ mixBlendMode: 'normal' }}
>
<g transform="scale(5.33333,5.33333)">
<path
d="M42,37c0,2.762 -2.238,5 -5,5h-26c-2.761,0 -5,-2.238 -5,-5v-26c0,-2.762 2.239,-5 5,-5h26c2.762,0 5,2.238 5,5z"
fill="#0288d1"
></path>
<path
d="M12,19h5v17h-5zM14.485,17h-0.028c-1.492,0 -2.457,-1.112 -2.457,-2.501c0,-1.419 0.995,-2.499 2.514,-2.499c1.521,0 2.458,1.08 2.486,2.499c0,1.388 -0.965,2.501 -2.515,2.501zM36,36h-5v-9.099c0,-2.198 -1.225,-3.698 -3.192,-3.698c-1.501,0 -2.313,1.012 -2.707,1.99c-0.144,0.35 -0.101,1.318 -0.101,1.807v9h-5v-17h5v2.616c0.721,-1.116 1.85,-2.616 4.738,-2.616c3.578,0 6.261,2.25 6.261,7.274l0.001,9.726z"
fill="#ffffff"
></path>
</g>
</g>
</g>
<defs>
<clipPath id="clip0_2344_20">
<rect width="24" height="24" rx="2" fill="white" />
</clipPath>
</defs>
</svg>
);
}

View File

@@ -1,6 +1,6 @@
import type { SVGAttributes } from 'react';
import type { JSX } from "preact/jsx-runtime";
type ShareIconProps = SVGAttributes<SVGSVGElement>;
type ShareIconProps = JSX.SVGAttributes<SVGSVGElement>
export function ShareIcon(props: ShareIconProps) {
return (

View File

@@ -1,22 +1,22 @@
interface TwitterIconProps {
type TwitterIconProps = {
className?: string;
}
};
export function TwitterIcon(props: TwitterIconProps) {
const { className } = props;
return (
<svg
width="23"
height="23"
viewBox="0 0 23 23"
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<rect width="23" height="23" rx="3" fill="currentColor" />
<path
d="M12.9285 10.3522L18.5135 4H17.1905L12.339 9.5144L8.467 4H4L9.8565 12.3395L4 19H5.323L10.443 13.1754L14.533 19H19M5.8005 4.97619H7.833L17.1895 18.0718H15.1565"
fill="#E5E5E5"
d="M8.9285 6.35221L14.5135 0H13.1905L8.339 5.5144L4.467 0H0L5.8565 8.33955L0 15H1.323L6.443 9.17535L10.533 15H15M1.8005 0.976187H3.833L13.1895 14.0718H11.1565"
fill="currentColor"
/>
</svg>
);

View File

@@ -91,7 +91,6 @@ export function TeamPricing() {
{
'top-full': !isCopied,
'top-0': isCopied,
'opacity-0': !isCopied,
},
)}
>

View File

@@ -1,30 +0,0 @@
import { useState } from 'react';
import { X } from 'lucide-react';
type PaidResourceDisclaimerProps = {
onClose: () => void;
};
export function PaidResourceDisclaimer(props: PaidResourceDisclaimerProps) {
const { onClose } = props;
return (
<div className="relative ml-3 mt-4 rounded-md bg-gray-100 p-3 px-3 text-xs text-gray-500">
<button className="absolute right-1 top-1" onClick={onClose}>
<X size={16} className="absolute right-2 top-2 cursor-pointer" />
</button>
<p className="mb-1 font-medium text-gray-800">
Note on Premium Resources
</p>
<p className="mb-1">
These are optional paid resources vetted by the roadmap team.
</p>
<p>
If you purchase a resource, we may receive a small commission at no
extra cost to you. This helps us offset the costs of running this site
and keep it free for everyone.
</p>
</div>
);
}

View File

@@ -1,33 +0,0 @@
import { type LucideIcon, Star } from 'lucide-react';
import { cn } from '../../lib/classname.ts';
type ResourceSeparatorProps = {
text: string;
className?: string;
labelClassName?: string;
icon?: LucideIcon;
};
export function ResourceListSeparator(props: ResourceSeparatorProps) {
const { text, icon: Icon, className = '', labelClassName = '' } = props;
return (
<p
className={cn(
'relative mt-6 flex items-center justify-start text-purple-600',
className,
)}
>
<span
className={cn(
'relative left-3 z-50 inline-flex items-center gap-1 rounded-md border border-current bg-white px-2 py-0.5 text-xs font-medium',
labelClassName,
)}
>
{Icon && <Icon className="inline-block h-3 w-3 fill-current" />}
{text}
</span>
<hr className="absolute inset-x-0 flex-grow border-current" />
</p>
);
}

View File

@@ -22,7 +22,8 @@ import type {
RoadmapContentDocument,
} from '../CustomRoadmap/CustomRoadmap';
import { markdownToHtml, sanitizeMarkdown } from '../../lib/markdown';
import { Ban, Coins, FileText, HeartHandshake, Star, X } from 'lucide-react';
import { cn } from '../../lib/classname';
import { Ban, FileText, HeartHandshake, X } from 'lucide-react';
import { getUrlParams, parseUrl } from '../../lib/browser';
import { Spinner } from '../ReactIcons/Spinner';
import { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx';
@@ -30,12 +31,8 @@ import { GoogleIcon } from '../ReactIcons/GoogleIcon.tsx';
import { YouTubeIcon } from '../ReactIcons/YouTubeIcon.tsx';
import { resourceTitleFromId } from '../../lib/roadmap.ts';
import { lockBodyScroll } from '../../lib/dom.ts';
import { TopicDetailLink } from './TopicDetailLink.tsx';
import { ResourceListSeparator } from './ResourceListSeparator.tsx';
import { PaidResourceDisclaimer } from './PaidResourceDisclaimer.tsx';
type TopicDetailProps = {
resourceId?: string;
resourceTitle?: string;
resourceType?: ResourceType;
@@ -43,44 +40,21 @@ type TopicDetailProps = {
canSubmitContribution: boolean;
};
type PaidResourceType = {
_id?: string;
title: string;
type: 'course' | 'book' | 'other';
url: string;
topicIds: string[];
const linkTypes: Record<AllowedLinkTypes, string> = {
article: 'bg-yellow-300',
course: 'bg-green-400',
opensource: 'bg-black text-white',
'roadmap.sh': 'bg-black text-white',
roadmap: 'bg-black text-white',
podcast: 'bg-purple-300',
video: 'bg-purple-300',
website: 'bg-blue-300',
official: 'bg-blue-600 text-white',
feed: "bg-[#ce3df3] text-white"
};
const paidResourcesCache: Record<string, PaidResourceType[]> = {};
async function fetchRoadmapPaidResources(roadmapId: string) {
if (paidResourcesCache[roadmapId]) {
return paidResourcesCache[roadmapId];
}
const { response, error } = await httpGet<PaidResourceType[]>(
`${import.meta.env.PUBLIC_API_URL}/v1-list-roadmap-paid-resources/${roadmapId}`,
);
if (!response || error) {
console.error(error);
return [];
}
paidResourcesCache[roadmapId] = response;
return response;
}
const PAID_RESOURCE_DISCLAIMER_HIDDEN = 'paid-resource-disclaimer-hidden';
export function TopicDetail(props: TopicDetailProps) {
const {
canSubmitContribution,
resourceId: defaultResourceId,
isEmbed = false,
resourceTitle,
} = props;
const { canSubmitContribution, isEmbed = false, resourceTitle } = props;
const [hasEnoughLinks, setHasEnoughLinks] = useState(false);
const [contributionUrl, setContributionUrl] = useState('');
@@ -95,9 +69,6 @@ export function TopicDetail(props: TopicDetailProps) {
const [links, setLinks] = useState<RoadmapContentDocument['links']>([]);
const toast = useToast();
const [showPaidResourceDisclaimer, setShowPaidResourceDisclaimer] =
useState(false);
const { secret } = getUrlParams() as { secret: string };
const isGuest = useMemo(() => !isLoggedIn(), []);
const topicRef = useRef<HTMLDivElement>(null);
@@ -106,7 +77,6 @@ export function TopicDetail(props: TopicDetailProps) {
const [topicId, setTopicId] = useState('');
const [resourceId, setResourceId] = useState('');
const [resourceType, setResourceType] = useState<ResourceType>('roadmap');
const [paidResources, setPaidResources] = useState<PaidResourceType[]>([]);
// Close the topic detail when user clicks outside the topic detail
useOutsideClick(topicRef, () => {
@@ -117,20 +87,6 @@ export function TopicDetail(props: TopicDetailProps) {
setIsActive(false);
});
useEffect(() => {
if (resourceType !== 'roadmap' || !defaultResourceId) {
return;
}
setShowPaidResourceDisclaimer(
localStorage.getItem(PAID_RESOURCE_DISCLAIMER_HIDDEN) !== 'true',
);
fetchRoadmapPaidResources(defaultResourceId).then((resources) => {
setPaidResources(resources);
});
}, [defaultResourceId]);
// Toggle topic is available even if the component UI is not active
// This is used on the best practice screen where we have the checkboxes
// to mark the topic as done/undone.
@@ -269,13 +225,7 @@ export function TopicDetail(props: TopicDetailProps) {
// article at third
// videos at fourth
// rest at last
const order = [
'official',
'opensource',
'article',
'video',
'feed',
];
const order = ['official', 'opensource', 'article', 'video', 'feed'];
return order.indexOf(a.type) - order.indexOf(b.type);
});
@@ -330,12 +280,6 @@ export function TopicDetail(props: TopicDetailProps) {
const tnsLink =
'https://thenewstack.io/devops/?utm_source=roadmap.sh&utm_medium=Referral&utm_campaign=Topic';
const paidResourcesForTopic = paidResources.filter((resource) => {
const normalizedTopicId =
topicId.indexOf('@') !== -1 ? topicId.split('@')[1] : topicId;
return resource.topicIds.includes(normalizedTopicId);
});
return (
<div className={'relative z-[90]'}>
<div
@@ -433,120 +377,94 @@ export function TopicDetail(props: TopicDetailProps) {
)}
{links.length > 0 && (
<>
<ResourceListSeparator
text="Free Resources"
className="text-green-600"
icon={HeartHandshake}
/>
<ul className="ml-3 mt-4 space-y-1">
{links.map((link) => {
return (
<li key={link.id}>
<TopicDetailLink
url={link.url}
type={link.type}
title={link.title}
onClick={() => {
// if it is one of our roadmaps, we want to track the click
if (canSubmitContribution) {
const parsedUrl = parseUrl(link.url);
<ul className="mt-6 space-y-1">
{links.map((link) => {
return (
<li key={link.id}>
<a
href={link.url}
target="_blank"
className="group font-medium text-gray-800 underline underline-offset-1 hover:text-black"
onClick={() => {
// if it is one of our roadmaps, we want to track the click
if (canSubmitContribution) {
const parsedUrl = parseUrl(link.url);
window.fireEvent({
category: 'TopicResourceClick',
action: `Click: ${parsedUrl.hostname}`,
label: `${resourceType} / ${resourceId} / ${topicId} / ${link.url}`,
});
}
}}
/>
</li>
);
})}
</ul>
</>
)}
{paidResourcesForTopic.length > 0 && (
<>
<ResourceListSeparator text="Premium Resources" icon={Star} />
<ul className="ml-3 mt-3 space-y-1">
{paidResourcesForTopic.map((resource) => {
return (
<li key={resource._id}>
<TopicDetailLink
url={resource.url}
type={resource.type as any}
title={resource.title}
isPaid={true}
/>
</li>
);
})}
</ul>
{showPaidResourceDisclaimer && (
<PaidResourceDisclaimer
onClose={() => {
localStorage.setItem(
PAID_RESOURCE_DISCLAIMER_HIDDEN,
'true',
);
setShowPaidResourceDisclaimer(false);
}}
/>
)}
</>
window.fireEvent({
category: 'TopicResourceClick',
action: `Click: ${parsedUrl.hostname}`,
label: `${resourceType} / ${resourceId} / ${topicId} / ${link.url}`,
});
}
}}
>
<span
className={cn(
'mr-2 inline-block rounded px-1.5 py-0.5 text-xs uppercase no-underline',
link.type in linkTypes
? linkTypes[link.type]
: 'bg-gray-200',
)}
>
{link.type === 'opensource' ? (
<>
{link.url.includes('github') && 'GitHub'}
{link.url.includes('gitlab') && 'GitLab'}
</>
) : (
link.type
)}
</span>
{link.title}
</a>
</li>
);
})}
</ul>
)}
{/* Contribution */}
{canSubmitContribution &&
!hasEnoughLinks &&
contributionUrl &&
hasContent && (
<div className="mb-12 mt-3 border-t text-sm text-gray-400 sm:mt-12">
<div className="mb-4 mt-3">
<p className="">
Find more resources using these pre-filled search
queries:
</p>
<div className="mt-3 flex gap-2 text-gray-700">
<a
href={googleSearchUrl}
target="_blank"
className="flex items-center gap-2 rounded-md border border-gray-300 px-3 py-1.5 pl-2 text-xs hover:border-gray-700 hover:bg-gray-100"
>
<GoogleIcon className={'h-4 w-4'} />
Google
</a>
<a
href={youtubeSearchUrl}
target="_blank"
className="flex items-center gap-2 rounded-md border border-gray-300 px-3 py-1.5 pl-2 text-xs hover:border-gray-700 hover:bg-gray-100"
>
<YouTubeIcon className={'h-4 w-4 text-red-500'} />
YouTube
</a>
</div>
</div>
<p className="mb-2 mt-2 leading-relaxed">
This popup should be a brief introductory paragraph for
the topic and a few links to good articles, videos, or any
other self-vetted resources. Please consider submitting a
PR to improve this content.
{canSubmitContribution && !hasEnoughLinks && contributionUrl && hasContent && (
<div className="mb-12 mt-3 border-t text-sm text-gray-400 sm:mt-12">
<div className="mb-4 mt-3">
<p className="">
Find more resources using these pre-filled search queries:
</p>
<a
href={contributionUrl}
target={'_blank'}
className="flex w-full items-center justify-center rounded-md bg-gray-800 p-2 text-sm text-white transition-colors hover:bg-black hover:text-white disabled:bg-green-200 disabled:text-black"
>
<GitHubIcon className="mr-2 inline-block h-4 w-4 text-white" />
Help us Improve this Content
</a>
<div className="mt-3 flex gap-2 text-gray-700">
<a
href={googleSearchUrl}
target="_blank"
className="flex items-center gap-2 rounded-md border border-gray-300 px-3 py-1.5 pl-2 text-xs hover:border-gray-700 hover:bg-gray-100"
>
<GoogleIcon className={'h-4 w-4'} />
Google
</a>
<a
href={youtubeSearchUrl}
target="_blank"
className="flex items-center gap-2 rounded-md border border-gray-300 px-3 py-1.5 pl-2 text-xs hover:border-gray-700 hover:bg-gray-100"
>
<YouTubeIcon className={'h-4 w-4 text-red-500'} />
YouTube
</a>
</div>
</div>
)}
<p className="mb-2 mt-2 leading-relaxed">
This popup should be a brief introductory paragraph for the topic and a few links
to good articles, videos, or any other self-vetted resources. Please consider
submitting a PR to improve this content.
</p>
<a
href={contributionUrl}
target={'_blank'}
className="flex w-full items-center justify-center rounded-md bg-gray-800 p-2 text-sm text-white transition-colors hover:bg-black hover:text-white disabled:bg-green-200 disabled:text-black"
>
<GitHubIcon className="mr-2 inline-block h-4 w-4 text-white" />
Help us Improve this Content
</a>
</div>
)}
</div>
{resourceId === 'devops' && (
<div className="mt-4">
@@ -610,4 +528,4 @@ export function TopicDetail(props: TopicDetailProps) {
<div className="fixed inset-0 z-30 bg-gray-900 bg-opacity-50 dark:bg-opacity-80"></div>
</div>
);
}
}

View File

@@ -1,57 +0,0 @@
import { cn } from '../../lib/classname.ts';
import type { AllowedLinkTypes } from '../CustomRoadmap/CustomRoadmap.tsx';
const linkTypes: Record<AllowedLinkTypes, string> = {
article: 'bg-yellow-300',
course: 'bg-green-400',
opensource: 'bg-black text-white',
'roadmap.sh': 'bg-black text-white',
roadmap: 'bg-black text-white',
podcast: 'bg-purple-300',
video: 'bg-purple-300',
website: 'bg-blue-300',
official: 'bg-blue-600 text-white',
feed: 'bg-[#ce3df3] text-white',
};
const paidLinkTypes: Record<string, string> = {
course: 'bg-yellow-300',
};
type TopicDetailLinkProps = {
url: string;
onClick?: () => void;
type: AllowedLinkTypes;
title: string;
isPaid?: boolean;
};
export function TopicDetailLink(props: TopicDetailLinkProps) {
const { url, onClick, type, title, isPaid = false } = props;
return (
<a
href={url}
target="_blank"
className="group font-medium text-gray-800 underline underline-offset-1 hover:text-black"
onClick={onClick}
>
<span
className={cn(
'mr-2 inline-block rounded px-1.5 py-0.5 text-xs uppercase no-underline',
(isPaid ? paidLinkTypes[type] : linkTypes[type]) || 'bg-gray-200',
)}
>
{type === 'opensource' ? (
<>
{url.includes('github') && 'GitHub'}
{url.includes('gitlab') && 'GitLab'}
</>
) : (
type
)}
</span>
{title}
</a>
);
}

View File

@@ -27,7 +27,7 @@ export function UserPublicProfileHeader(props: UserPublicProfileHeaderProps) {
: '/images/default-avatar.png'
}
alt={name}
className="h-32 w-32 object-cover rounded-full"
className="h-32 w-32 rounded-full"
/>
<div>

View File

@@ -385,7 +385,7 @@ As a recommendation for technology implementing this project, [Socket.io](http:/
![Content Delivery Network (CDN) Simulator](https://assets.roadmap.sh/guest/cdn-simulator-lv7kl.png)
For this particular backend project, were not going to focus on coding, but rather on backend tools and their configuration. A [CDN](https://aws.amazon.com/what-is/cdn/) (or Content Delivery Network) is a platform that allows you to serve static content (like text files, images, audio, etc) safely and reliably.
For this particular backend project, were not going to focus on coding, but rather on backend tools and their configuration. A [CDN](https://aws.amazon.com/es/what-is/cdn/) (or Content Delivery Network) is a platform that allows you to serve static content (like text files, images, audio, etc) safely and reliably.
Instead of having all files inside the same server, the content is replicated and distributed across a network of servers that can provide you with the files at any given point in time.
@@ -459,4 +459,4 @@ Feel free to add extra commands to make the navigation even more interactive.
With the last of our backend project ideas, youve covered all the major areas involved in backend development and youre more than ready to apply for a backend development job if you havent already.
If you find a piece of technology that wasnt covered here, youll have the skills required to pick it up in no time.
If you find a piece of technology that wasnt covered here, youll have the skills required to pick it up in no time.

View File

@@ -1,452 +0,0 @@
---
title: 'Top 10+ Backend Technologies to Use in @currentYear@: Expert Advice'
description: 'Looking for the best backend technologies in @currentYear@? Check out our expert list of top tools for developers.'
authorId: fernando
excludedBySlug: '/backend/technologies'
seo:
title: 'Top 10+ Backend Technologies to Use in @currentYear@: Expert Advice'
description: 'Looking for the best backend technologies in @currentYear@? Check out our expert list of top tools for developers.'
ogImageUrl: 'https://assets.roadmap.sh/guest/backend-technologies-pnof4.jpg'
isNew: true
type: 'textual'
date: 2024-08-27
sitemap:
priority: 0.7
changefreq: 'weekly'
tags:
- 'guide'
- 'textual-guide'
- 'guide-sitemap'
---
![Best backend development technologies.](https://assets.roadmap.sh/guest/backend-technologies-pnof4.jpg)
Backend technologies are the key to building robust and scalable applications. They power all platforms and products on the web without even being visible to the users.
While backend programming languages form the foundation of backend development, they aren't enough on their own. Understanding and leveraging the right backend technologies can significantly enhance your development workflow and application performance.
As a [backend developer](https://roadmap.sh/backend), youll be faced with too many options while trying to define your backend technology stack, and that can feel overwhelming.
So, in this article, were going to cover the best backend technologies in the following categories:
- Databases
- Version control systems
- Containerization and orchestration
- Cloud platforms
- APIs & Web Services
- Caching systems
- Message brokers
- Authentication and Authorization systems
- CI/CD
- Monitoring & Logging
These should help you stay up-to-date or reach the required level to succeed as a backend developer.
## Databases
![Databases](https://assets.roadmap.sh/guest/databases-4a1kz.png)
We cant have a list of backend technologies to learn without covering databases. After all, databases are a core piece of the best backend technologies in use today and the backbone of any application, providing the necessary storage and retrieval of data. Choosing the right type of database depends on your application's requirements, such as data consistency, scalability, and complexity.
### SQL Databases
SQL databases (or relational databases as theyre also called) bring structure to your data and a standard querying language known as SQL.
#### PostgreSQL
PostgreSQL is an advanced open-source relational database known for its reliability and extensive feature set. It supports a wide range of data types and complex queries, making it ideal for applications that require ACID compliance and advanced data handling capabilities. PostgreSQL is commonly used in financial systems, data warehousing, and applications needing strong data integrity and complex reporting.
PostgreSQL also offers robust support for JSON and JSONB data types, enabling seamless integration of relational and NoSQL capabilities within a single database system. Its powerful indexing mechanisms ensure efficient query performance even with large datasets.
Additionally, PostgreSQL provides advanced security features like row-level security and multi-factor authentication, making it a secure choice for handling sensitive data.
#### MySQL
MySQL is a widely used open-source SQL database praised for its speed, reliability, and ease of use. It is particularly popular backend technology for web applications and online transaction processing (OLTP) due to its performance and robust community support. MySQL is often the database of choice for content management systems, e-commerce platforms, and logging applications.
MySQL also supports a variety of storage engines, including InnoDB, which provides ACID compliance, foreign key support, and transaction-safe operations, making it suitable for a wide range of applications.
Its replication capabilities, including master-slave and group replication, ensure high availability and scalability for large-scale deployments. Additionally, MySQL offers advanced security features such as data encryption, user authentication, and role-based access control, enhancing its suitability for handling sensitive data.
#### Microsoft SQL Server
SQL Server is a relational database management system from Microsoft that offers great performance, scalability, and deep integration with other Microsoft products. It provides comprehensive tools for database management, including advanced analytics and business intelligence features. SQL Server is ideal for enterprise-level applications, data warehousing, and environments where integration with Microsoft services, such as Azure, is beneficial.
MSSQL Server also includes robust security features, such as transparent data encryption, dynamic data masking, and advanced threat protection, making it a trusted choice for handling sensitive data. It supports a wide range of data types, including spatial and XML data, and offers powerful indexing and query optimization techniques to ensure efficient data retrieval and processing.
SQL Server's integration with Visual Studio and other Microsoft development tools helps to streamline the development process.
#### SQLite
SQLite is a self-contained, serverless, and zero-configuration database engine known for its simplicity and ease of use. It is lightweight and efficient, making it perfect for small to medium-sized applications, mobile apps, desktop applications, and prototyping. SQLite is embedded within the application, eliminating the need for a separate database server, which simplifies deployment and maintenance.
Its single-disk file format makes it highly portable across various operating systems and platforms.
SQLite's efficient memory and disk usage allow it to perform well even on devices with limited resources, such as IoT devices and embedded systems.
This makes SQLite an excellent choice for applications where simplicity, reliability, and low overhead are essential.
### NoSQL Databases
On the other hand, NoSQL databases allow for more flexibility by removing the need for a fixed schema and structure to your data. Each solution presented here covers a different type of unstructured database, and its up to you to decide if that focus actually makes sense for your business logic or not.
#### MongoDB
MongoDB is a document-oriented database that offers flexibility and scalability. It handles unstructured data with ease, making it ideal for applications with large-scale data and real-time analytics. MongoDB is commonly used in content management systems, e-commerce platforms, and applications that require a dynamic schema. Its ability to store data in JSON-like documents allows for easy data retrieval and manipulation.
#### DynamoDB
DynamoDB is a fully managed NoSQL database service provided by AWS. It is designed for high-performance applications requiring seamless scalability and high availability. DynamoDB is best suited for high-traffic web applications, gaming, and IoT applications. Its serverless nature means it can automatically scale up or down based on demand, ensuring consistent performance and cost-efficiency.
#### Cassandra
Cassandra is an open-source distributed NoSQL database known for its high availability and fault tolerance without compromising performance. It is ideal for large-scale applications and real-time big data analytics. Cassandra's distributed architecture makes it perfect for environments requiring continuous availability and the ability to handle large amounts of data across multiple nodes. It is commonly used in social media platforms, recommendation engines, and other data-intensive applications.
## Version Control Systems
![Version Control Systems](https://assets.roadmap.sh/guest/version-control-flow-bzojr.png)
Version control systems are essential for managing changes to source code over time, allowing multiple developers to collaborate effectively and maintain a history of changes.
### Git
When it comes to picking the right version control tool, Git is the most widely used one. It provides a powerful, flexible, and distributed model for tracking changes. Gits architecture supports nonlinear development, allowing multiple branches to be created, merged, and managed independently. This makes Git essential for code collaboration and version tracking, making it a foundational tool for any developer.
Lets go through some of the key benefits that make Git one of the leading backend technologies in web development.
#### Distributed Version Control
Unlike centralized version control systems (CVCS) where a single central repository holds the entire project history, Git allows each developer to have a complete copy of the repository, including its history. This decentralized approach enhances collaboration and ensures that work can continue even if the central server is down.
#### Branching and Merging
**Branching**: Gits lightweight branching model allows developers to create, delete, and switch between branches effortlessly. This facilitates isolated development of features, bug fixes, or experiments without impacting the main codebase.
**Merging**: Git provides powerful merging capabilities to integrate changes from different branches. Tools like merge commits and rebasing help manage and resolve conflicts, ensuring a smooth integration process.
#### Performance
Git is designed to handle everything from small to very large projects with speed and efficiency. Its performance for both local operations (like committing and branching) and remote operations (like fetching and pushing changes) is optimized, making it suitable for high-performance needs.
#### Commit History and Tracking
Commit Granularity: Git encourages frequent commits, each with a descriptive message, making it easier to track changes, understand the project history, and identify when and why a change was made.
**History Viewing**: Commands like git log, git blame, and git bisect allow developers to explore the projects history, pinpoint the introduction of bugs, and understand the evolution of the codebase.
#### Collaboration
While strictly not part of Gits feature set, these functionalities enhance the basic set of features provided by the version control system.
**Pull Requests**: Platforms like GitHub, GitLab, and Bitbucket build on Gits capabilities, offering features like pull requests to facilitate code reviews and discussions before integrating changes into the main branch.
**Code Reviews**: Integrating with continuous integration (CI) systems, Git platforms enable automated testing and code quality checks, ensuring that changes meet project standards before merging.
#### Staging Area
Gits staging area (or index) provides an intermediate area where changes can be formatted and reviewed before committing. This allows for more granular control over what changes are included in a commit.
### GitHub
GitHub is a web-based platform that leverages Git for version control. It provides an extensive list of collaborative features, including (as already mentioned) pull requests, code reviews, and project management tools.
#### Key Features and Benefits
**Pull Requests and Code Reviews**: Facilitate discussions around proposed changes before integrating them into the main codebase. Developers can review code, leave comments, and suggest improvements. Built-in tools for reviewing code changes ensure collaborations are following coding standards and catch potential issues early.
**Project Management**: GitHub Issues allow tracking of bugs, enhancements, and tasks. Milestones help in organizing issues into targeted releases or sprints. Kanban-style boards provide a visual way to manage tasks, track progress, and organize workflows.
**Continuous Integration and Deployment**: Automate workflows for CI/CD, testing, deployment, and more. GitHub Actions supports custom scripts and pre-built actions to streamline DevOps processes.
**Community and Collaboration**: Developers can host static websites directly from a GitHub repository with Github Pages, theyre ideal for project documentation or personal websites. Integrated wikis can be used for detailed project documentation. And through forking, starring, and following repositories the platform encourages collaboration and knowledge sharing.
GitHubs extensive features and strong community support make it the de facto choice for many companies and developers, both for open-source and private projects.
### GitLab
GitLab is a web-based platform for version control using Git, known for its robust CI/CD pipeline integration. It offers a comprehensive set of tools for the entire DevOps lifecycle, making it suitable for continuous integration, deployment, and monitoring.
#### Key Features and Benefits
**Integrated CI/CD**: Built-in continuous integration and continuous deployment pipelines allow backend developers to automate building, testing, and deploying code changes. With Gitlabs they can even automatically configure CI/CD pipelines, deploy applications, and monitor performance, all through the same platform.
**Security and Compliance**: Gitlabs provides key security capabilities for backend development: built-in static and dynamic application security testing (SAST/DAST).
**Collaboration and Communication**: Instead of Pull Requests like Github, Gitlabs provides the concept of “Merge Requests”: a simplified code review process with inline comments and suggestions.
GitLabs all-in-one platform makes it an excellent choice for teams looking to streamline their DevOps processes and improve collaboration and productivity.
### Bitbucket
Bitbucket is a Git-based source code repository hosting service that provides both commercial plans and free accounts for small teams. It integrates seamlessly with Atlassian products like Jira and Trello, making it a great choice for teams already using these tools.
**Repository Hosting**: Bitbucket supports both Git and Mercurial version control systems. And it offers unlimited private repositories for teams.
**Integration with Atlassian Products**: Seamlessly integrates with Jira for issue tracking and project management. It can create branches from Jira issues and view development progress which is a fantastic integration for big teams using both tools. If, on the other hand, youre using Trello, it can connect to Trellos boards for visual task management and tracking.
**Continuous Integration and Deployment**: Integrated CI/CD service for automating builds, tests, and deployments. It can be configured with a YAML file for custom workflows.
**Security and Permissions**: Control who accesses specific branches to enforce workflows and protect critical branches. You can even enhance security with two-factor authentication.
Bitbuckets integration with Atlassians suite of products, along with its robust CI/CD capabilities, make it an attractive option for teams seeking a tightly integrated development and project management environment.
## Containerization and Orchestration
![Containerization and Orchestration](https://assets.roadmap.sh/guest/containers-and-orchestrators-jb6xj.png)
While backend developers arent always directly involved in the deployment process, understanding the basics of containerization and orchestration can help them work and interact with the team in charge of devops (who usually set up these CI/CD pipelines).
While this is not an exhaustive list of backend technologies, the two main ones to learn about are:
### Docker
Docker is a platform for developing, shipping, and running applications in containers. Containers package software and its dependencies, ensuring it runs consistently across different environments. Docker simplifies application deployment and testing, making it ideal for microservices architectures and continuous integration/continuous deployment (CI/CD) pipelines.
### Kubernetes
Kubernetes is an open-source system for automating the deployment, scaling, and management of containerized applications. It orchestrates containers across clusters of machines, providing high availability, scalability, and efficient resource utilization. Kubernetes is perfect for complex, large-scale applications requiring robust infrastructure management and automated scaling.
## Cloud Platforms
![Cloud Platforms](https://assets.roadmap.sh/guest/cloud-providers-ownec.png)
Cloud platforms provide a range of services and infrastructure that allow developers to deploy, manage, and scale applications without maintaining physical servers. Mind you, the “cloud” is nothing else than someone elses servers that you dont have to manage.
These platforms all offer very similar types of managed services (each with its own flavor) that allow you to set up powerful and scalable infrastructures with a few clicks.
### Amazon Web Services (AWS)
Amazon Web Services (AWS) is a very complete cloud computing platform offered by Amazon. It provides a broad range of services, including computing power, storage solutions, and databases, catering to various needs and applications.
#### Key Characteristics of AWS
**Scalability**: AWS provides scalable solutions that allow businesses to easily adjust resources based on demand.
Global Reach: With data centers located worldwide, AWS offers high availability and low latency for global applications.
**Diverse Service Offerings**: AWS offers a wide range of services, including EC2 for computing, S3 for storage, and RDS for databases.
**Security and Compliance**: AWS provides robust security features and complies with numerous industry standards and regulations.
**Cost Management**: Flexible pricing models and cost management tools help businesses optimize their cloud spending.
### Google Cloud Platform (GCP)
Google Cloud Platform (GCP) is a suite of cloud computing services provided by Google. Like AWS and Microsoft Azure, GCP offers a variety of services, including computing power, storage, machine learning, and data analytics.
#### Key Characteristics of GCP
**AI and Machine Learning**: GCP excels in providing advanced AI and machine learning tools, leveraging Google's expertise.
**Big Data and Analytics**: GCP offers powerful analytics tools, including BigQuery, for handling large-scale data processing.
**Networking**: GCP provides a robust and secure global network infrastructure.
**Integration with Google Services**: Seamless integration with Google Workspace and other Google services enhances productivity and collaboration.
**Open Source Support**: GCP supports various open-source technologies, promoting flexibility and innovation.
### Microsoft Azure
Microsoft Azure is a cloud computing service created by Microsoft, offering a wide range of cloud services, including those for computing, analytics, storage, and networking.
#### Key Characteristics of Microsoft Azure
**Integration with Microsoft Products**: Azure offers seamless integration with popular Microsoft software and services.
**Hybrid Cloud Capabilities**: Azure supports hybrid cloud environments, enabling smooth integration between on-premises and cloud resources.
**Comprehensive Service Range**: Azure provides a broad spectrum of services, including Azure Virtual Machines, Azure SQL Database, and Azure DevOps.
**Enterprise-Grade Security**: Azure emphasizes security with advanced features and compliance with industry standards.
**Developer and IT Pro Tools**: Azure offers a wide range of tools for developers and IT professionals, including Visual Studio and Azure DevOps.
At a high level, all of these providers are very similar to each other, to the point where backend developers experienced in one of them, can extrapolate their understanding of the environment into others with minimum ramp-up time.
## APIs and Web Services
![APIs and Web Services](https://assets.roadmap.sh/guest/rest-vs-graphql-vs-grpc-tp40c.png)
APIs (or Application Programming Interfaces) and web services are another mandatory incorporation to the list of top backend technologies any developer should keep in mind. They enable communication between different software systems.
The three most common types of APIs right now, are REST, GraphQL and gPRC, lets take a closer look at each one of them.
### REST
REST is a standard architecture for web services, known for its simplicity and scalability. It operates on stateless principles and uses standard HTTP methods (GET, POST, PUT, DELETE) to perform CRUD (Create, Read, Update, Delete) operations. RESTful APIs are typically used to access and manipulate web resources using URLs.
REST is ideal for web applications and services due to its ease of implementation and broad compatibility with various web technologies. It is commonly used for developing APIs for web and mobile applications, providing endpoints that clients can interact with to perform various operations. RESTful APIs are also ideal for integrating with third-party services, enabling data exchange and interaction between different systems.
#### Key Characteristics of REST
**Statelessness**: Each request from a client contains all the information needed to process the request, without relying on stored context on the server.
**Uniform Interface**: REST APIs follow standard conventions, making them easy to understand and use. This includes using standard HTTP methods and status codes.
**Client-Server Architecture**: Separates the client and server concerns, improving scalability and flexibility. Clients handle the user interface and user experience, while servers handle data storage and business logic.
**Cacheability**: Responses from REST APIs can be cached to improve performance, reducing the need for repeated requests.
**Layered System**: REST allows for a layered system architecture, enabling intermediaries like load balancers and proxy servers to enhance security, performance, and scalability.
If youd like to know more about REST, you can read the full definition directly from [its source here](https://ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm).
### GraphQL
GraphQL is a query language for APIs and a runtime for executing those queries by using a type system you define for your data. Unlike REST, where multiple endpoints return fixed data structures, GraphQL allows clients to request exactly the data they need. This flexibility reduces the amount of data transferred over the network and can significantly improve performance.
GraphQL is ideal for applications with complex and dynamic data requirements.
#### Key Characteristics of GraphQL
**Declarative Data Fetching**: Clients specify the structure of the response, ensuring they receive only the data they need.
**Strongly Typed Schema**: The API schema is strongly typed, providing clear and detailed documentation of available data and operations.
**Single Endpoint**: Unlike REST, GraphQL uses a single endpoint to serve all requests, simplifying the API architecture.
**Real-time Data**: Supports real-time updates through subscriptions, enabling clients to receive live data changes.
### gRPC
gRPC is a high-performance, open-source RPC (Remote Procedure Call) framework developed by Google. gRPC is designed for low-latency, high-throughput communication, making it suitable for microservices architectures and real-time communication systems.
gRPC is ideal for applications that require efficient, reliable, and bi-directional communication.
#### Key Characteristics of gRPC
**Protocol Buffers**: Uses Protocol Buffers for compact, efficient, and platform-neutral serialization of structured data.
**HTTP/2**: Utilizes HTTP/2 for multiplexing, flow control, header compression, and efficient binary transport.
**Bi-directional Streaming**: Supports multiple types of streaming, including client-side, server-side, and bi-directional streaming.
**Cross-Language Compatibility**: Provides support for multiple backend programming languages, enabling interoperability between different systems.
## Caching Systems
![Caching Systems](https://assets.roadmap.sh/guest/working-cache-11kis.png)
Caching systems store copies of frequently accessed data to reduce latency and improve application performance. They are essential for speeding up data retrieval and reducing the load on primary data stores.
Implementing a successful caching strategy is not trivial, and one key aspect of it is the backend technology used for the implementation. While there might be multiple options out there, the industry currently recognizes only one de facto choice: Redis.
### Redis: a fast in-memory storage solution
Redis is an in-memory data structure store that can function as a database, cache, and message broker. It supports various data structures such as strings, hashes, lists, sets, sorted sets, bitmaps, hyperloglogs, and with the right add-ons, even vectors. Redis uses a key-value storage mechanism, which makes it simple yet powerful for a wide range of use cases.
Lets quickly review some of the characteristics of Redis that make it such a fantastic option.
#### High Availability and Scalability
- **Redis Sentinel**: Provides high availability and monitoring, automatically promoting a slave to master in case of failure, ensuring minimal downtime.
- **Redis Cluster**: Supports automatic sharding, allowing Redis to scale horizontally. It partitions data across multiple nodes, ensuring that the system can handle large datasets and high throughput.
#### Performance and Use Cases
Redis's in-memory architecture gives it unmatched I/O speed, making it ideal for real-time applications such as:
- **Gaming**: Managing leaderboards, player sessions, and real-time statistics.
- **Chat Applications**: Storing messages, user presence information, and delivering real-time notifications.
- **Analytics**: Real-time data processing and analytics, where rapid data access and manipulation are crucial.
- **Caching**: Reducing database load by caching frequently accessed data, improving application response times.
#### Persistence and Durability
- **RDB (Redis Database)**: Creates snapshots of the dataset at specified intervals, allowing data to be restored from the last snapshot.
- **AOF (Append Only File)**: Logs every write operation received by the server, providing a more durable solution that can replay the log to reconstruct the dataset.
- **Hybrid Approach**: Combining RDB and AOF to leverage the benefits of both methods, balancing performance and data durability.
#### Advanced Features
On top of all of that, Redis even provides some very powerful out-of-the-box features:
- **Lua Scripting**: Supports server-side scripting with Lua, enabling complex operations to be executed atomically.
- **Pub/Sub Messaging**: Allows for message broadcasting to multiple clients, supporting real-time messaging and notifications. You can create whole event-based architectures around Redis.
- **Modules**: Extend Redis functionality with custom modules, such as RedisGraph for graph database capabilities and RedisJSON for JSON document storage.
Redis's robust feature set, combined with its high performance and flexibility, makes it a versatile tool for developers looking to build scalable and responsive applications.
## Message Brokers and Streaming Platforms
![Message Brokers and Streaming Platforms](https://assets.roadmap.sh/guest/message-queue-yoq3q.png)
Message brokers and streaming platforms facilitate communication between different parts of a system, enabling efficient data exchange and processing. They are crucial for building scalable and resilient applications and they are the core of reactive architectures (also known as event-based architectures).
### RabbitMQ
RabbitMQ is an open-source message broker that implements the Advanced Message Queuing Protocol (AMQP). It supports multiple messaging protocols and can be deployed in distributed and federated configurations. RabbitMQ is ideal for use cases that require reliable message delivery, complex routing, and interoperability with other messaging systems. It is commonly used in financial systems, order processing, and other applications that need robust messaging capabilities.
### Apache Kafka
Apache Kafka is a distributed streaming platform designed for high-throughput, low-latency data processing. It excels at handling real-time data feeds, making it suitable for applications that require continuous data integration and processing. Kafkas publish-subscribe messaging system is fault-tolerant and scalable, making it ideal for big data applications, real-time analytics, event sourcing, and log aggregation. Its ability to store streams of records in a fault-tolerant manner also makes it useful for building event-driven architectures and microservices.
As backend developers, understanding how to take advantage of these message queues is critical to the development of scalable and resilient platforms. It is definitely a must-have skill and you need to master it.
## Authentication and Authorization
![Authentication and Authorization](https://assets.roadmap.sh/guest/authentication-vs-authorization-vl6lg.png)
Authentication and authorization technologies are essential for securing applications, ensuring that users are who they claim to be and have the appropriate permissions to access resources.
This space is filled with solutions and methodologies, so its not easy to pick one option here, however, these two are very common solutions used to implement both, authZ (authorization) and authN (authentication).
### OAuth
OAuth is an open standard for access delegation commonly used to grant websites or applications limited access to a users information without exposing their passwords. It is widely used in single sign-on (SSO) systems, enabling users to log in to multiple applications with a single set of credentials. OAuth is ideal for third-party applications that need access to user data, such as social media integrations and API access management.
### JWT (JSON Web Tokens)
JWT is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object, which is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure. JWTs are commonly used for authentication and authorization in web applications, providing a secure way to transmit information between parties. They are particularly useful in stateless authentication systems, where user state is not stored on the server (like when dealing with RESTful APIs).
## CI/CD Pipelines
![CI/CD Pipelines](https://assets.roadmap.sh/guest/continous-development-vs-continuous-integration-rg7t9.png)
CI/CD (Continuous Integration/Continuous Deployment) pipelines automate the process of code integration, testing, and deployment, enabling faster and more reliable software delivery. This is one of the key areas backend developers need to understand to avoid creating code that simply gets in the way of the deployment process.
### GitHub Actions
GitHub Actions is an integrated CI/CD service within GitHub repositories, allowing developers to automate build, test, and deployment workflows. It supports a wide range of actions and integrations, making it highly customizable and versatile for various development workflows.
### CircleCI
CircleCI is a continuous integration and delivery platform that automates the building, testing, and deployment of applications. It supports multiple backend languages and integrates with various version control systems, making it a popular choice for diverse development environments. CircleCI is known for its speed and ease of setup, providing robust tools for optimizing and monitoring CI/CD pipelines.
### GitLab CI/CD
GitLab CI/CD is an integrated part of the GitLab platform (similar to how GitHub actions are a part of GitHub), offering continuous integration, delivery, and deployment features within the GitLab ecosystem. It allows developers to manage their entire DevOps lifecycle in a single application, from planning and coding to monitoring and security. GitLab CI/CD is particularly useful for teams seeking a seamless and comprehensive CI/CD solution.
### Jenkins
If instead of a SaaS, youre looking for a solution that you can potentially self-host, then you might want to look into Jenkins. Jenkins is an open-source automation server that provides hundreds of plugins to support building, deploying, and automating your software development process. It is highly extensible and can be integrated with a wide array of tools and technologies. Jenkins is ideal for complex, large-scale projects requiring a customizable and powerful CI/CD environment.
## Monitoring and Logging
![Monitoring and Logging](https://assets.roadmap.sh/guest/server-monitoring-vk5nb.png)
Understanding how the systems that you develop behave and perform on a daily basis is crucial to launching a successful product. Heres where monitoring and logging come into play. Monitoring and logging are crucial pieces of backend technology used for maintaining the health, performance, and security of applications. These tools help detect issues, analyze performance, and ensure system reliability.
### ELK Stack (Elasticsearch, Logstash, Kibana)
The ELK Stack is a set of tools for searching, analyzing, and visualizing log data in real time. Elasticsearch is a search and analytics engine, Logstash is a server-side data processing pipeline, and Kibana is a visualization tool. Together, they provide a powerful platform for centralized logging and monitoring, making them ideal for applications requiring detailed log analysis and real-time insights.
### Grafana
Grafana is an open-source platform for monitoring and observability that integrates with various data sources. It provides powerful visualizations, dashboards, and alerting capabilities, making it a popular choice for monitoring infrastructure and application performance. Grafana is particularly useful for teams needing a flexible and customizable monitoring solution.
### Loki
Loki is a log aggregation system designed to work with Grafana. It is optimized for cost-effective and scalable logging, making it suitable for applications with high log volumes. Loki simplifies log management by allowing developers to query logs using the same language as Grafana, providing seamless integration for comprehensive observability.
### Prometheus
Prometheus is an open-source monitoring and alerting toolkit designed for reliability and scalability. It collects and stores metrics as time series data, providing powerful querying language and alerting capabilities. Prometheus is ideal for monitoring applications and infrastructure, particularly in cloud-native and microservices environments, where dynamic and ephemeral resources are common.
In the end, you might want to go with one or several of these options, the point is that you, as a developer, should be aware of them and what type of value they add to the project.
## Conclusion
As backend developers, focusing on a backend programming language and a backend framework is not going to be enough. The backend ecosystem is very rich, and there are many areas that are either directly or indirectly related to the daily tasks that a backend dev needs to work on.
This is why you need to stay up-to-date and look at the trends that develop within each area to make sure youre still working with and focusing on the right solutions.
If you'd like more details on the type of backend development technologies you should be focusing on to excel at your role as a backend developer, check out our [Backend Developer roadmap](https://roadmap.sh/backend).

View File

@@ -132,7 +132,7 @@ As a DevOps professional, you can decide to go for any of these following DevOps
- Automation expert
- General DevOps engineer
- System engineer
- DevOps architect
- DevOps erchitect
- DevOps release manager
- DevSecOps engineer
- DevOps test engineer

View File

@@ -1,48 +0,0 @@
---
title: 'Accessible Form UI'
description: 'Create an accessible form UI using HTML and CSS.'
isNew: false
sort: 7
difficulty: 'beginner'
nature: 'Accessibility'
skills:
- 'HTML'
- 'CSS'
- 'Layouts'
- 'Positioning'
- 'Accessibility'
seo:
title: 'Create an Accessible Form UI for a Website Using HTML and CSS'
description: 'Learn how to create an accessible form component using HTML and CSS.'
keywords:
- 'accessible forms'
- 'css project idea'
- 'responsive design'
- 'html and css'
roadmapIds:
- 'frontend'
---
In this project, you are required to create a form UI using only HTML and CSS. The form will include fields for a full name, email, password, and confirm password, along with a button to toggle the visibility of the password text. Additionally, the form will feature a completeness progress bar and a checklist of requirements that must be met for the form to reach 100% completeness. While this version of the form wont be functional, it will be a static UI component that can be enhanced with JavaScript in the future.
The goal of this project is to not only help you practice your HTML and CSS but also to focus on creating an accessible form that is easy to use for all users, including those with disabilities. Given below is the rough mockup of the form UI that you need to create:
[![Form UI](https://assets.roadmap.sh/guest/form-components-7t4b3.png)](https://assets.roadmap.sh/guest/form-components-7t4b3.png)
## Accessibility Guidelines
You should read up on accessibility guidelines and best practices before starting this project. However, here are some key points to keep in mind while creating an accessible form UI:
- **Labeling**: Ensure that each form field has a corresponding `<label>` element that is clearly associated with the field using the `for` attribute.
- **Focus State**: Style the focus state of each input field so that users navigating with a keyboard can easily see which field is currently active.
- **Error Messaging**: Consider adding space for error messages that can be displayed when a user inputs invalid data. These messages should be clearly associated with the relevant input field.
- **ARIA Attributes**: Use ARIA (Accessible Rich Internet Applications) attributes where necessary, such as `aria-required` for required fields and `aria-invalid` for fields with errors.
- **Color Contrast**: Ensure that the color contrast between text and background is sufficient to meet WCAG (Web Content Accessibility Guidelines) standards, making the form readable for users with visual impairments.
- **Interactive Elements**: Make sure that the button to show/hide the password is accessible via keyboard and screen readers, providing clear feedback on the current state (e.g., "Password is hidden" or "Password is visible").
Once done, you can test the form UI using a screen reader or browser extensions like Axe or Lighthouse to check for accessibility issues and make necessary adjustments.
---
After completing this project, you will have a solid foundation in creating accessible and well-structured forms using HTML and CSS. You can later enhance this form by adding JavaScript to make it fully functional and dynamic in future projects.

View File

@@ -1,30 +0,0 @@
---
title: 'Accordion'
description: 'Create an accordion component using HTML, CSS, and JavaScript.'
isNew: false
sort: 18
difficulty: 'beginner'
nature: 'JavaScript'
skills:
- 'HTML'
- 'CSS'
- 'JavaScript'
- 'DOM Manipulation'
seo:
title: 'Build an Accordion Component with JavaScript'
description: 'Learn how to create a responsive accordion component that allows users to toggle between different sections of content.'
keywords:
- 'accordion'
- 'javascript accordion'
- 'html and css'
roadmapIds:
- 'frontend'
---
You are required to create an accordion component that displays a list of questions or headings. When a user clicks on a question, its corresponding answer or content section will expand while collapsing any previously opened section. This allows only one section to be open at a time, keeping the UI clean and organized.
Given below is the mockup showing the accordion in its default and expanded states:
[![Accordion](https://assets.roadmap.sh/guest/accordion-rbvpo.png)](https://assets.roadmap.sh/guest/accordion-rbvpo.png)
This project will help you practice DOM manipulation, event handling, and implementing responsive design patterns using JavaScript.

View File

@@ -1,36 +0,0 @@
---
title: 'Github Actions Workflow'
description: 'Write GitHub Actions workflow to deploy a simple GitHub Pages site.'
isNew: true
sort: 3
difficulty: 'beginner'
nature: 'CI/CD'
skills:
- 'devops'
- 'github actions'
- 'ci/cd'
seo:
title: 'Github Actions Workflow'
description: 'Write GitHub Actions workflow to deploy a simple GitHub Pages site.'
keywords:
- 'basic ci/cd'
- 'devops'
- 'devops projects'
roadmapIds:
- 'git-github'
- 'devops'
---
In this project, you will write a basic HTML file and setup a GitHub Actions workflow to test, build & deploy it to GitHub Pages.
## Requirements
- Create a simple HTML file (the content is up to you)
- Create a GitHub Actions workflow that will test, build & deploy the website to [GitHub Pages](https://pages.github.com/).
- Failures in the workflow should be clearly indicated and failures will halt the workflow
- The workflow should be in the `.github/workflows` directory
- The workflow file should be named `main.yml`
<hr />
If you are looking to build a more advanced version of this project, you can either create a more advanced Astro website or you can build a more advanced GitHub Actions workflow.

View File

@@ -1,53 +0,0 @@
---
title: 'Basic HTML Website'
description: 'Create simple HTML only website with multiple pages.'
isNew: false
sort: 2
difficulty: 'beginner'
nature: 'HTML'
skills:
- 'HTML'
- 'Layouts'
- 'semantic HTML'
seo:
title: 'Basic HTML Website Project'
description: 'Create a simple HTML only website with multiple pages.'
keywords:
- 'basic html'
- 'html project idea'
roadmapIds:
- 'frontend'
---
> Goal of this project is to teach you how to structure a website using HTML i.e. different sections of a website like header, footer, navigation, main content, sidebars etc. Do not style the website, only focus on the structure. Styling will be done in separate projects.
In this project, you are required to create a simple HTML only website with multiple pages. The website should have following pages:
- Homepage
- Projects
- Articles
- Contact
The website should have a navigation bar that should be present on all pages and link to all the pages.
You are not required to style the website, you are only required to create the structure of the website using HTML. Goals of this project are:
- Learn how to create multiple pages in a website.
- Structure a website using HTML in a semantic way.
- Structure in a way that you can easily add styles later.
- Add SEO meta tags to the website.
You can use the following mockup example to create the structure of the website (remember, you are not required to style the website, only focus on the structure that you can style later):
![Basic HTML Website](https://assets.roadmap.sh/guest/portfolio-design-83lku.png)
Again, make sure that your submission includes the following:
- Semantically correct HTML structure.
- Multiple pages with a navigation bar.
- SEO meta tags in the head of each page.
- Contact page should have a form with fields like name, email, message etc.
<hr />
After completing this project, you will have a good understanding of how to structure a website using HTML, basic SEO meta tags, HTML tags, forms etc. You can now move on to the next project where you will learn how to style this website using CSS.

View File

@@ -1,42 +0,0 @@
---
title: 'Basic Infrastructure as Code with Terraform'
description: 'Provision a simple cloud infrastructure using Terraform'
isNew: false
sort: 4
difficulty: 'beginner'
nature: 'CLI'
skills:
- 'terraform'
- 'devops'
- 'iac'
- 'cloud'
seo:
title: 'Basic Infrastructure as Code with Terraform'
description: 'Learn to provision cloud resources using Terraform'
keywords:
- 'terraform'
- 'infrastructure as code'
- 'cloud provisioning'
- 'devops'
roadmapIds:
- 'devops'
- 'terraform'
- 'aws'
---
In this project, you will use Terraform to provision a virtual machine in AWS.
## Requirements
- Install Terraform on your local machine.
- Set up an account with a AWS and obtain necessary credentials.
- Create a `main.tf` file in the root directory of your project.
- Write Terraform configuration to provision a basic resource (e.g., an EC2 instance on AWS or a VM on Azure).
- Use Terraform commands to initialize, plan, apply, and destroy your infrastructure.
- The provisioned resource should be accessible and verifiable in your cloud provider's console.
You can learn more about Terraform basics [here](https://learn.hashicorp.com/terraform).
<hr />
For a more advanced version of this project, consider adding multiple resources, using variables and outputs, or implementing a modular structure for your Terraform configuration.

View File

@@ -1,35 +0,0 @@
---
title: 'Changelog Component'
description: 'Create a changelog component for a website using HTML and CSS.'
isNew: false
sort: 4
difficulty: 'beginner'
nature: 'CSS'
skills:
- 'HTML'
- 'Layouts'
- 'CSS'
- 'Flexbox'
seo:
title: 'Create a Changelog Component Website Using HTML and CSS'
description: 'Learn how to create a changelog component for a website using HTML and CSS.'
keywords:
- 'basic css'
- 'css project idea'
- 'responsive design'
- 'html and css'
roadmapIds:
- 'frontend'
---
In this project you are required to create a simple component for a website that displays a changelog. A changelog is a log or record of all notable changes made to a project or software. It is often used to keep users informed about the latest updates and improvements.
The goal of this project is to teach you about positioning and layout in CSS. You will create a simple HTML structure and use CSS to style it into a visually appealing and responsive changelog component. Given below is a rough mockup of the changelog component you need to create.
[![Changelog Component](https://assets.roadmap.sh/guest/changelog-component-1m86j.png)](https://assets.roadmap.sh/guest/changelog-component-1m86j.png)
Feel free to customize the design and layout of the component as you see fit. The focus should be on creating a well-structured and responsive component that can be easily integrated into a website.
---
After completing this project, you will have a good understanding of how to create simple layouts using HTML and CSS. You can further enhance your skills by exploring more complex layouts, such as grids and flexbox, in future projects.

View File

@@ -1,32 +0,0 @@
---
title: 'Cookie Consent'
description: 'Create a simple cookie consent banner using JavaScript.'
isNew: false
sort: 12
difficulty: 'beginner'
nature: 'JavaScript'
skills:
- 'HTML'
- 'CSS'
- 'JavaScript'
- 'DOM Manipulation'
seo:
title: 'Create a Cookie Consent Popup Using HTML, CSS, and JavaScript'
description: 'Learn how to build a cookie consent popup with basic JavaScript for managing user consent.'
keywords:
- 'cookie consent'
- 'javascript popup'
- 'html and css'
- 'javascript project'
roadmapIds:
- 'frontend'
---
This project is designed to introduce you to basic DOM manipulation and event handling in JavaScript.
Many websites display a cookie consent popup to inform users about the use of cookies and to obtain their consent. In this project, you will create a simple cookie consent popup that appears when the user visits the page. The popup will include a message and a button to accept the consent. Once accepted, the popup will disappear. Given below is an example of how the popup might look:
[![Cookie Consent Popup](https://assets.roadmap.sh/guest/cookie-consent-banner-07etz.png)](https://assets.roadmap.sh/guest/cookie-consent-banner-07etz.png)
Bonus points if you persist the user's consent using cookies or local storage and prevent the popup from appearing on subsequent visits.

View File

@@ -1,30 +0,0 @@
---
title: 'Custom Dropdown'
description: 'Create a custom dropdown using HTML, CSS, and JavaScript.'
isNew: false
sort: 19
difficulty: 'intermediate'
nature: 'JavaScript'
skills:
- 'HTML'
- 'CSS'
- 'JavaScript'
- 'DOM Manipulation'
seo:
title: 'Build a Custom Dropdown Menu with JavaScript'
description: 'Learn how to create a fully customizable dropdown menu that allows users to select an item and see the selection reflected in the dropdown.'
keywords:
- 'custom dropdown'
- 'javascript dropdown'
- 'html and css'
roadmapIds:
- 'frontend'
---
You will create a custom dropdown menu that lets users select an item from a list. The dropdown should have a default state showing a placeholder text, an open state revealing all options, and a selected state where the chosen item is displayed. When an item is selected, the dropdown closes, and the selected item is highlighted.
Given below is the mockup showing the dropdown in its default, open, and selected states:
[![Custom Dropdown](https://assets.roadmap.sh/guest/dropdown-1f4b3.png)](https://assets.roadmap.sh/guest/dropdown-1f4b3.png)
This project will help you practice DOM manipulation, event handling, and creating responsive and interactive elements with JavaScript.

View File

@@ -1,36 +0,0 @@
---
title: 'Datepicker UI'
description: 'Create a simple datepicker UI using HTML and CSS.'
isNew: false
sort: 6
difficulty: 'beginner'
nature: 'CSS'
skills:
- 'HTML'
- 'CSS'
- 'Layouts'
- 'Positioning'
seo:
title: 'Create a Datepicker UI for a Website Using HTML and CSS'
description: 'Learn how to create a datepicker component using HTML and CSS.'
keywords:
- 'basic css'
- 'css project idea'
- 'responsive design'
- 'html and css'
roadmapIds:
- 'frontend'
---
In this project, you are required to create a simple datepicker UI using only HTML and CSS. It will not be a functional datepicker, but a static UI component that you can later enhance with JavaScript.
The goal of this project is to help you practice positioning, layout, and styling techniques in CSS. Below is a rough mockup showing the datepicker UI you need to create.
[![Datepicker UI](https://assets.roadmap.sh/guest/datepicker-ui-7l480.png)](https://assets.roadmap.sh/guest/datepicker-ui-7l480.png)
Feel free to customize the colors, fonts, and overall design to match your style.
---
While this version won't be functional, it will provide a solid foundation for creating an interactive datepicker in a future project.

View File

@@ -1,39 +0,0 @@
---
title: 'Docker Web Server'
description: 'Create a Web Server using Docker & NGINX'
isNew: false
sort: 3
difficulty: 'beginner'
nature: 'CLI'
skills:
- 'docker'
- 'devops'
- 'nginx'
- 'web'
seo:
title: 'Docker Web Server'
description: 'Create a Web Server using Docker & NGINX'
keywords:
- 'docker web server'
- 'docker'
- 'system administration'
- 'web server'
roadmapIds:
- 'devops'
- 'docker'
---
In this project, you will create an NGINX web server that will serve a simple HTML page using Docker.
## Requirements
- The Dockerfile should be named `Dockerfile`.
- The Dockerfile should be in the root directory of the project.
- The build process will add a local HTML file to the container, which will be accessible to NGINX.
- The simple HTML page will be accessible to you from `localhost:8080`
You can learn more about writing a Dockerfile [here](https://docs.docker.com/engine/reference/builder/).
<hr />
If you are looking to build a more advanced version of this project, you can consider using the `alpine:latest` image and setting up NGINX yourself rather than using the official NGINX image.

View File

@@ -1,39 +0,0 @@
---
title: 'GitHub Random Repository'
description: 'Create a GitHub random repository finder using GitHub API.'
isNew: false
sort: 25
difficulty: 'intermediate'
nature: 'API Integration'
skills:
- 'HTML'
- 'CSS'
- 'JavaScript'
- 'API Integration'
- 'DOM Manipulation'
seo:
title: 'Build a GitHub Repository Finder with JavaScript and GitHub API'
description: 'Learn how to create a dynamic application that fetches random GitHub repositories based on a chosen language and displays key information like stars, forks, and issues.'
keywords:
- 'github api'
- 'repository finder'
- 'javascript project'
roadmapIds:
- 'frontend'
---
This project is designed to introduce you to working with external APIs, handling asynchronous requests, and managing different UI states with JavaScript.
You will create a GitHub repository finder that allows users to select a programming language from a dropdown menu. The app will then use the GitHub Repository Search API to fetch and display a random repository that matches the selected language. The displayed information should include the repository name, description, number of stars, forks, and open issues. Users can fetch another random repository with a button click.
[![GitHub Random Repository](https://assets.roadmap.sh/guest/github-repo-finder-n2qz4.png)](https://assets.roadmap.sh/guest/github-repo-finder-n2qz4.png)
The application should handle loading, empty, and error states effectively. After successfully fetching a repository, a "Refresh" button should appear to allow users to get another random repository.
Here are the links to the resources you will need for this project:
- [GitHub Repository Search API](https://docs.github.com/en/rest/reference/search#search-repositories)
- [Programming Language Data](https://raw.githubusercontent.com/kamranahmedse/githunt/master/src/components/filters/language-filter/languages.json)
This project will help you practice API integration, managing asynchronous data, and enhancing user experience with responsive UI states.

View File

@@ -1,51 +0,0 @@
---
title: 'Image Grid Layout'
description: 'Create a grid layout of images using HTML and CSS.'
isNew: false
sort: 8
difficulty: 'beginner'
nature: 'CSS'
skills:
- 'HTML'
- 'CSS'
- 'Grid Layout'
- 'Responsive Design'
seo:
title: 'Create an Image Grid Layout for a Website Using HTML and CSS'
description: 'Learn how to create a responsive grid layout of images using HTML and CSS.'
keywords:
- 'css grid'
- 'image layout'
- 'responsive design'
- 'html and css'
roadmapIds:
- 'frontend'
---
In this project, you are required to create a grid layout using HTML and CSS. You will be provided with six images that need to be arranged in a grid pattern based on the provided mockup. The primary focus of this project is to help you learn and practice the CSS Grid layout technique, which is essential for creating responsive and flexible web layouts.
The goal of this project is to give you hands-on experience with CSS Grid, allowing you to create complex layouts with ease. Below is a rough mockup showing the grid layout you need to create along with the six images that you should use.
[![Grid Layout Mockup](https://assets.roadmap.sh/guest/image-grid.jpg)](https://assets.roadmap.sh/guest/image-grid.jpg)
You can use the same images provided in the mockup or replace them with your own images. The grid layout should be responsive, meaning it should adapt to different screen sizes and maintain a visually appealing design.
- [A foggy beach with a large rock formation in the foreground](https://unsplash.com/photos/a-foggy-beach-with-a-large-rock-formation-in-the-foreground-TTExgxV06KA)
- [A living room with a white couch and a round window](https://unsplash.com/photos/a-living-room-with-a-white-couch-and-a-round-window-Wuu6H3mI7UA)
- [A table topped with plates and bowls of food](https://unsplash.com/photos/a-table-topped-with-plates-and-bowls-of-food-zx8_8jwZ5m8)
- [A building with a red door and a tree in front of it](https://unsplash.com/photos/a-building-with-a-red-door-and-a-tree-in-front-of-it-uTd-kylh7bE)
- [A row of white apartment buildings next to a street](https://unsplash.com/photos/a-row-of-white-apartment-buildings-next-to-a-street-f1PzRPbqt0M)
- [A view of a beach from the top of a hill](https://unsplash.com/photos/a-view-of-a-beach-from-the-top-of-a-hill-SAyIShcE5rs)
Key learning objectives of this project include:
- **Grid Structure**: Understand the fundamentals of CSS Grid, including defining grid containers, rows, columns, and how to place items within the grid.
- **Responsive Design**: Learn how to make the grid layout responsive so that it adapts to different screen sizes. This might involve changing the number of columns or the layout of the images based on the viewport width.
- **Alignment and Spacing**: Explore how to align grid items and manage spacing between them to achieve a clean and visually appealing layout.
---
By completing this project, you will gain confidence in using CSS Grid to create flexible and responsive layouts. You can further apply these skills to more complex projects as you continue learning web design and development.

View File

@@ -1,57 +0,0 @@
---
title: 'Local Monitoring System with Docker'
description: 'Set up a local monitoring system using Docker with Grafana and Prometheus'
isNew: false
sort: 1
difficulty: 'intermediate'
nature: 'CLI'
skills:
- 'docker'
- 'devops'
- 'monitoring'
- 'grafana'
- 'prometheus'
seo:
title: 'Local Monitoring System with Docker, Grafana, and Prometheus'
description: 'Learn to set up a local monitoring system using Docker with Grafana and Prometheus'
keywords:
- 'docker'
- 'monitoring'
- 'grafana'
- 'prometheus'
- 'devops'
roadmapIds:
- 'devops'
- 'docker'
---
In this project, you will set up a local monitoring system using Docker, Grafana, and Prometheus. This setup will allow you to collect metrics and visualize them in a dashboard.
## Requirements
- Docker and Docker Compose installed on your local machine.
- Create a `docker-compose.yml` file in the root directory of your project.
- Set up Prometheus as the metrics collection system.
- Configure Grafana as the visualization tool.
- Create a simple dashboard in Grafana to display system metrics.
- Add a sample application to monitor, such as a simple web server.
Your `docker-compose.yml` file should define services for:
1. Prometheus
2. Grafana
3. A sample application to monitor
## Steps
1. Create the `docker-compose.yml` file with services for Prometheus and Grafana.
2. Configure Prometheus to scrape metrics (you'll need a `prometheus.yml` configuration file).
3. Set up Grafana to use Prometheus as a data source.
4. Create a simple dashboard in Grafana to display metrics.
5. Use `docker-compose up` to start your monitoring stack.
6. Access Grafana through your web browser and verify that metrics are being collected and displayed.
You can learn more about Prometheus [here](https://prometheus.io/docs/introduction/overview/) and Grafana [here](https://grafana.com/docs/grafana/latest/).
<hr />
For a more advanced version of this project, consider adding alerting rules in Prometheus, setting up additional exporters to collect more diverse metrics, or monitoring a multi-container application.

View File

@@ -1,54 +0,0 @@
---
title: 'Personal Portfolio'
description: 'Convert the previous simple HTML website into a personal portfolio.'
isNew: false
sort: 3
difficulty: 'beginner'
nature: 'CSS'
skills:
- 'CSS'
- 'Responsive Design'
- 'Box Model'
- 'Typography'
- 'Flexbox'
seo:
title: 'Create a Personal Portfolio Website Using HTML and CSS'
description: 'Learn how to style a website using CSS by converting a simple HTML website into a personal portfolio.'
keywords:
- 'basic css'
- 'css project idea'
- 'responsive design'
- 'html and css'
roadmapIds:
- 'frontend'
---
> The goal of this project is to teach you how to style a website using CSS. You will take the structure from the [previous HTML-only project](/projects/basic-html-website) and apply various CSS techniques to enhance its appearance and responsiveness.
In this project, you will style the HTML website structure you created previously [in a different project](/projects/basic-html-website). The focus will be on learning how to use CSS to create responsive layouts, apply color and typography, and enhance the overall design of your website.
Rough mockups of the website structure for mobile and desctop devices are given below. Do not worry about the design details i.e. colors backgrounds etc at this stage; we are not looking for a beautiful design, but a well-structured and responsive website. Just focus on making the layout same as the mockup and ensuring it looks good on different screen sizes.
[![Styled HTML Website](https://assets.roadmap.sh/guest/portfolio-template-xdhki.png)](https://assets.roadmap.sh/guest/portfolio-template-xdhki.png)
## Submission Requirements
Your submission should include:
- A fully styled, responsive website with the same structure as the previous project.
- Consistent use of a chosen color scheme and typography.
- Proper use of CSS techniques like Flexbox, media queries, and the box model.
- A responsive navigation bar and well-styled contact form.
## Bonus Points
For bonus points, you can:
- Use [Google Fonts](https://fonts.google.com/) to enhance the typography of your website.
- Look into [GitHub Pages](https://pages.github.com/) or [Cloudflare Pages](https://pages.cloudflare.com/) to host your website for free.
- Add support for dark mode using CSS variables.
---
After completing this project, you will have a solid understanding of how to style a basic HTML website using CSS. You can move on to more advanced topics, such as CSS animations, transitions, and grid layouts, in future projects.

View File

@@ -1,42 +0,0 @@
---
title: 'Reddit Client'
description: 'Create a Reddit client with customizable subreddit lanes.'
isNew: false
sort: 26
difficulty: 'intermediate'
nature: 'API Integration'
skills:
- 'HTML'
- 'CSS'
- 'JavaScript'
- 'API Integration'
- 'DOM Manipulation'
- 'Asynchronous Programming'
seo:
title: 'Build a Multi-Lane Reddit Client with JavaScript and Reddit API'
description: 'Learn how to create a dynamic browser-based Reddit client that allows users to add and view multiple subreddits in customizable lanes.'
keywords:
- 'reddit api'
- 'subreddit viewer'
- 'javascript project'
- 'multi-lane client'
roadmapIds:
- 'frontend'
---
You are required to create a browser-based Reddit client that displays multiple subreddits in separate, customizable lanes. You'll work with the Reddit JSON feed to fetch posts from different subreddits and display them in a dynamic, responsive layout.
The application will allow users to add new subreddit lanes by entering a subreddit name. It will verify the existence of the subreddit, fetch its posts, and display them in a new lane. Each lane will show the subreddit's posts, including titles, authors, and vote counts.
[![Multi-Lane Reddit Client](https://assets.roadmap.sh/guest/reddit-client-o876k.png)](https://assets.roadmap.sh/guest/reddit-client-o876k.png)
To fetch data from reddit, you can use the JSON feed available at the following URL. You can also use the Reddit API to fetch more details about the posts, such as comments, upvotes, and more.
```plaintext
https://www.reddit.com/r/{subreddit}.json
```
The application should handle loading states while fetching data, display error messages for invalid subreddits or API issues, and provide a smooth user experience when adding or removing lanes. You can use local storage to save the user's custom lanes and restore them when the application is reloaded.
This project will help you practice API integration, state management, asynchronous programming, and creating a responsive, dynamic user interface. It's an excellent opportunity to enhance your skills in frontend development and working with real-time data.

View File

@@ -1,29 +0,0 @@
---
title: 'Restricted Textarea'
description: 'Create a textarea with live character count and a max character limit.'
isNew: false
sort: 15
difficulty: 'beginner'
nature: 'JavaScript'
skills:
- 'HTML'
- 'CSS'
- 'JavaScript'
- 'DOM Manipulation'
seo:
title: 'Build a Restricted Textarea with JavaScript'
description: 'Learn how to create a textarea with live character count and a maximum limit, with visual feedback as the limit is reached.'
keywords:
- 'character count'
- 'textarea limit'
- 'javascript input'
- 'html and css'
roadmapIds:
- 'frontend'
---
You are required to create a textarea that tracks and displays the number of characters typed by the user, along with a maximum character limit. As the user types, the character count will update dynamically. Once the limit is reached, the textarea will prevent further input and the border will turn red to visually indicate the limit has been hit.
[![Restricted Textarea](https://assets.roadmap.sh/guest/textarea-input-vdclr.png)](https://assets.roadmap.sh/guest/textarea-input-vdclr.png)
This project will help you practice manipulating input elements with JavaScript, handling user input events, and providing real-time feedback to enhance user experience.

View File

@@ -1,32 +0,0 @@
---
title: 'Tabs'
description: 'Create a simple tabs component using HTML, CSS, and JavaScript.'
isNew: false
sort: 10
difficulty: 'beginner'
nature: 'JavaScript'
skills:
- 'HTML'
- 'CSS'
- 'JavaScript'
- 'DOM Manipulation'
seo:
title: 'Create a Tabs Functionality Using HTML, CSS, and JavaScript'
description: 'Learn how to build a tabs component with basic JavaScript for switching between content sections.'
keywords:
- 'javascript tabs'
- 'dynamic content'
- 'html and css'
- 'javascript project'
roadmapIds:
- 'frontend'
---
This project is designed to introduce you to basic DOM manipulation and event handling in JavaScript.
You are required to create a simple tabs functionality using HTML, CSS, and basic JavaScript. The page will have four tabs, with the first tab being active by default. When the user clicks on another tab, the content of the current tab will be hidden, and the content of the selected tab will be displayed.
[![Tabs Component Mockup](https://assets.roadmap.sh/guest/simple-tabs-8e6gy.png)](https://assets.roadmap.sh/guest/simple-tabs-8e6gy.png)
This project will help you practice selecting elements with JavaScript, listen for click events, and manipulate the dom to show or hide relevant tab content.

View File

@@ -1,49 +0,0 @@
---
title: 'Single-Page CV'
description: 'Create a single-page HTML CV to showcase your career history'
isNew: false
sort: 1
difficulty: 'beginner'
nature: 'HTML'
skills:
- 'HTML'
- 'Semantic HTML'
- 'Layout'
- 'SEO'
seo:
title: 'Single-Page HTML CV Project'
description: 'Create a simple single-page HTML CV that displays your education, skills, and career history.'
keywords:
- 'html cv'
- 'single-page cv'
- 'html resume'
roadmapIds:
- 'frontend'
---
> The goal of this project is to teach you how to create a structured, single-page CV using only HTML. You will focus on laying out your education, skills, and career history in a clean, semantic manner. Styling will be addressed in a later project.
In this project, you are required to create a single-page CV (Curriculum Vitae) using only HTML. Your webpage should look like the following image:
![Single-Page HTML CV](https://assets.roadmap.sh/guest/resume-template-zyl70.png)
Key requirements for this project:
- **Semantic HTML**: Use appropriate HTML tags to structure your CV.
- **SEO Meta Tags**: Include essential meta tags for SEO.
- **Open Graph (OG) Tags**: Add OG tags for better social media sharing.
- **Favicon**: Add a favicon for your CV page.
The structure of your CV should be easily understandable and ready for styling in a future project.
### Submission Checklist:
- Semantically correct HTML structure.
- Single-page layout with sections for education, skills, and career history.
- SEO meta tags in the head section.
- OG tags for better social media sharing.
- A favicon linked in the head section.
<hr />
By completing this project, you'll gain a solid understanding of how to create a single-page CV using HTML, apply basic SEO principles, and prepare your webpage for future styling. This foundation will enable you to move on to styling the CV using CSS in subsequent projects.

View File

@@ -1,34 +0,0 @@
---
title: 'Task Tracker'
description: 'Create a task tracker with a to-do list using JavaScript.'
isNew: false
sort: 22
difficulty: 'intermediate'
nature: 'JavaScript'
skills:
- 'HTML'
- 'CSS'
- 'JavaScript'
- 'DOM Manipulation'
seo:
title: 'Build a Task Tracker with JavaScript'
description: 'Learn how to create a dynamic task tracker that allows users to add, complete, and delete tasks with real-time updates.'
keywords:
- 'task tracker'
- 'to-do list'
- 'javascript project'
roadmapIds:
- 'frontend'
---
You are required to create a task tracker that lets users add new tasks, mark them as complete, or delete them. Completed tasks will be moved to the end of the list and will have strikethrough, and users can unmark tasks to return them to the pending list.
Here is the mockup of the task tracker:
[![Task Tracker](https://assets.roadmap.sh/guest/task-tracker-2diba.png)](https://assets.roadmap.sh/guest/task-tracker-2diba.png)
## Hint
Store your tasks in an array of objects, where each object represents a task with properties like description and status (completed or not). Whenever a new task is added, updated, deleted, or marked as complete/uncomplete, update the tasks array. Write a function `renderTasks` which will remove all tasks from the DOM and re-render them based on the updated tasks array.
This project will help you practice array manipulation, event handling, and dynamic DOM updates using JavaScript.

View File

@@ -1,33 +0,0 @@
---
title: Temperature Converter
description: Build a temperature converter that converts between different units.
isNew: false
sort: 27
difficulty: intermediate
nature: JavaScript
skills:
- HTML
- CSS
- JavaScript
- DOM Manipulation
seo:
- title: Build a Temperature Converter with JavaScript
- description: Learn how to create an interactive temperature converter that converts between Celsius, Fahrenheit, and Kelvin using JavaScript.
- keywords:
- 'temperature converter'
- 'javascript project'
- 'unit conversion'
- 'html and css'
roadmapIds:
- 'frontend'
---
This project is designed to help you practice DOM manipulation, form handling, and basic calculations in JavaScript.
You will create a temperature converter that allows users to enter a temperature value, select the unit they want to convert from, and select the unit they want to convert to. The "Convert" button should only be enabled when all three fields are filled in. Once the user clicks "Convert," the tool will display the converted temperature below the form.
Here is a mockup of what the temperature converter might look like:
[![Temperature Converter](https://assets.roadmap.sh/guest/temperature-converter-8omel.png)](https://assets.roadmap.sh/guest/temperature-converter-8omel.png)
This project will help you gain experience with handling user input, conditionally enabling form elements, and performing simple calculations using JavaScript.

View File

@@ -1,37 +0,0 @@
---
title: 'Testimonial Cards'
description: 'Create testimonial cards for a website using HTML and CSS.'
isNew: false
sort: 5
difficulty: 'beginner'
nature: 'CSS'
skills:
- 'HTML'
- 'CSS'
- 'Layouts'
- 'Flexbox'
- 'Positioning'
seo:
title: 'Create Testimonial Cards for a Website Using HTML and CSS'
description: 'Learn how to create testimonial components using HTML and CSS.'
keywords:
- 'basic css'
- 'css project idea'
- 'responsive design'
- 'html and css'
roadmapIds:
- 'frontend'
---
In this project, you are required to create a bunch of testimonial cards. Testimonials are quotes or statements from satisfied customers or users, often used on websites to build credibility and trust.
The goal of this project is to teach you about positioning and layout in CSS. Below is a rough mockup showing some testimonial cards. Each card is designed to help you understand different layout and positioning techniques.
[![Testimonials Component](https://assets.roadmap.sh/guest/testimonials-min-3j2j4.png)](https://assets.roadmap.sh/guest/testimonials-min-3j2j4.png)
Feel free to use any content and images you like for the testimonials.
---
After completing this project, you will have a good understanding of how to create layouts using HTML and CSS. You can further enhance your skills by exploring more complex projects as you progress.

View File

@@ -1,34 +0,0 @@
---
title: 'Tooltip UI'
description: 'Create a tooltip for navigation items using only HTML and CSS.'
isNew: false
sort: 9
difficulty: 'beginner'
nature: 'CSS'
skills:
- 'HTML'
- 'CSS'
- 'Positioning'
- 'Hover Effects'
seo:
title: 'Create a CSS Tooltip for Navigation Items'
description: 'Learn how to create a tooltip that appears above navigation items on hover using only HTML and CSS.'
keywords:
- 'css tooltip'
- 'hover effects'
- 'navigation menu'
- 'html and css'
roadmapIds:
- 'frontend'
---
In this project, you are required to create a tooltip that appears above navigation items when hovered, using only HTML and CSS. A tooltip is a small pop-up box that provides additional information about a navigation item when a user hovers over it. This project will focus on mastering CSS positioning, hover effects, and creating visually appealing tooltips without relying on JavaScript.
The goal of this project is to help you understand how to use CSS for dynamic UI effects. You will learn how to position elements relative to each other, create smooth transitions, and make your navigation more interactive and user-friendly. Below is a rough mockup showing the tooltip appearing above a navigation item.
[![Tooltip Mockup](https://assets.roadmap.sh/guest/tooltip-zh8gm.png)](https://assets.roadmap.sh/guest/tooltip-zh8gm.png)
Bonus points for different animations for the tooltip, such as fade-in, slide-in, or scale-in effects.
After completing this project, you will have a better understanding of CSS positioning, hover effects, and creating interactive UI elements without JavaScript.

View File

@@ -1,8 +0,0 @@
# Animations
`Animations` can add visual cues that notify users about what's going on in your app. They are especially useful when the UI changes state, such as when new content loads or new actions become available. Animations also add a polished look to your app, which gives it a higher quality look and feel.
Visit the following resources to learn more:
- [@official@Google developers: Animations](https://developer.android.com/develop/ui/views/animations/overview)
- [@video@Google developers: Animations](https://www.youtube.com/watch?v=N_x7SV3I3P0)

View File

@@ -1,8 +0,0 @@
# ConstraintLayout
Lets you create large, complex layouts with a flat view hierarchy—no nested view groups. It's similar to `RelativeLayout` in that all views are laid out according to relationships between sibling views and the parent layout, but it's more flexible than RelativeLayout and easier to use. Its available on xml and jetpack compose.
Visit the following resources to learn more:
- [@official@Android developers: ConstraintLayout in xml](https://developer.android.com/develop/ui/views/layout/constraint-layout)
- [@official@Android developers: ContraintLayout in compose](https://developer.android.com/develop/ui/compose/layouts/constraintlayout)

View File

@@ -1,8 +0,0 @@
# Drawer
The **Navigation Drawer** in Android is a sliding menu from the left that simplifies navigation between important app links. It opens by sliding or via an icon in the `ActionBar`. Its an overlay panel that replaces a screen dedicated to displaying options.
Visit the following resources to learn more:
- [@official@Android developers: DrawerLayout](https://developer.android.com/reference/androidx/drawerlayout/widget/DrawerLayout)
- [@article@Navigate Drawer Tutorial](https://www.digitalocean.com/community/tutorials/android-navigation-drawer-example-tutorial)

View File

@@ -1,9 +0,0 @@
# ListView
Displays a vertically-scrollable collection of views, where each view is positioned immediatelybelow the previous view in the list.
For a more modern, flexible, and performant approach to displaying lists, use `RecyclerView`.
Visit the following resources to learn more:
- [@official@Android developers: ListView](https://developer.android.com/reference/android/widget/ListView)

View File

@@ -1,9 +0,0 @@
# RelativeLayout
A **RelativeLayout** in Android is a type of ViewGroup that allows you to position child views relative to each other or relative to the parent layout. It's a flexible layout where you can arrange the child views in relation to one another based on certain rules, making it suitable for creating complex UI designs.
**RelativeLayout** was commonly used in earlier Android development, but with the introduction of `ConstraintLayout`, it's less frequently used in modern apps.
Visit the following resources to learn more:
- [@official@Android developers: Relative Layout](https://developer.android.com/develop/ui/views/layout/relative)

View File

@@ -2579,6 +2579,39 @@
"focusable": true,
"resizing": false
},
{
"id": "Wc2ybRw43uamEtno0FpDv",
"type": "subtopic",
"position": {
"x": -99.73327447982547,
"y": 957.2304293708296
},
"selected": false,
"data": {
"label": "Template Ref Vars",
"style": {
"fontSize": 17,
"justifyContent": "flex-start",
"textAlign": "center"
},
"oldId": "nyDry6ZWyEUuTq4pw-lU3"
},
"zIndex": 999,
"width": 225,
"height": 49,
"style": {
"width": 225,
"height": 49
},
"positionAbsolute": {
"x": -99.73327447982547,
"y": 957.2304293708296
},
"dragging": false,
"resizing": false,
"selectable": true,
"focusable": true
},
{
"id": "VsU6713jeIjAOEZnF6gWx",
"type": "subtopic",

View File

@@ -1,8 +1 @@
# Build Environments
You can define different named build configurations for your project, such as `development` and `production`, with different defaults. Each named configuration can have defaults for any of the options that apply to the various builder targets, such as `build`, `serve`, and `test`. The Angular CLI can replace files for each environment if you pass a `--configuration` flag with the named configuration when running a CLI command.
Visit the following resources to learn more:
- [@official@Angular Official Docs - Build environments](https://angular.dev/tools/cli/environments#using-environment-specific-variables-in-your-app)
- [@article@Building an Angular application in various environments using Angular CLI and server](https://medium.com/yavar/building-an-angular-application-in-various-environments-using-angular-cli-and-server-18f94067154b)
# Build Environments

View File

@@ -1,8 +1 @@
# @case
If no `@case` matches the `@switch` condition and there is no `@default` block, nothing is shown. Otherwise, the content inside the `@case` that matches the condition will be displayed.
Visit the following resources to learn more:
- [@official@Angular Official Docs - @switch](https://angular.dev/guide/templates/control-flow#switch-block---selection)
- [@article@Angular @switch: Complete Guide](https://blog.angular-university.io/angular-switch/)
# @case

View File

@@ -1,9 +1 @@
# CLI Builders
A number of Angular CLI commands run a complex process on your code, such as building, testing, or serving your application. The commands use an internal tool called `Architect` to run CLI builders, which invoke another tool (bundler, test runner, server) to accomplish the desired task. Custom builders can perform an entirely new task or to change which third-party tool is used by an existing command.
Visit the following resources to learn more:
- [@official@Angular Official Docs - CLI Builders](https://angular.dev/tools/cli/cli-builder)
- [@video@Angular Builders Creating Custom Builder from Scratch](https://www.youtube.com/watch?v=QbDkDLnXAZE)
- [@opensource@Angular Builders](https://github.com/just-jeb/angular-builders)
# CLI Builders

View File

@@ -1,18 +1 @@
# Communication
Angular components can communicate with each other using `@Input()` and `@Output()` decorators. These decorators facilitate data exchange between parent and child components.
- **@Input()**: This decorator allows a parent component to pass data to a child component, enabling the child to receive and use the data.
- **@Output()**: This decorator allows a child component to emit events to a parent component, enabling the parent to respond to changes or actions within the child component.
Additionally, **model inputs** are a special type of input that enable two-way data binding. This means that changes in the child component can be propagated back to the parent component, ensuring synchronization between the two. Model inputs automatically create a corresponding output, typically named by appending “Change” to the inputs name, to facilitate this two-way communication.
To facilitate communication between unrelated components, its most effective to trigger events using `EventEmitter` and have the components listen for these events. This approach ensures a decoupled and flexible architecture, allowing components to interact seamlessly without direct dependencies.
Visit the following resources to learn more:
- [@official@Angular Official Website - Inputs](https://angular.dev/guide/components/inputs)
- [@official@Angular Official Website - Outputs](https://angular.dev/guide/components/outputs)
- [@official@Angular Official Docs - Model Inputs](https://angular.dev/guide/signals/model)
- [@official@Custom events with outputs](https://angular.dev/guide/components/outputs)
- [@video@Non-Related Component Communication | Angular Component & Directives](https://www.youtube.com/watch?v=aIkGXMJFTzM)
# Communication

View File

@@ -1,9 +1 @@
# Creating Libraries
If you have developed features that are suitable for reuse, you can create your own libraries. These libraries can be used locally in your workspace, or you can publish them as npm packages to share with other projects or other Angular developers. Putting code into a separate library is more complex than simply putting everything in one application. It requires more of an investment in time and thought for managing, maintaining, and updating the library. This complexity can pay off when the library is being used in multiple applications.
Visit the following resources to learn more:
- [@official@Angular Official Docs - Creating Libraries](https://angular.dev/tools/libraries/creating-libraries)
- [@official@Angular Official Docs - File Structure: Library project files](https://angular.dev/reference/configs/file-structure#library-project-files)
- [@opensource@NG Packagr](https://github.com/ng-packagr/ng-packagr)
# Creating Libraries

View File

@@ -1,10 +1 @@
# Cross-site Request Forgery
Cross-site request forgery, also known as one-click attack or session riding and abbreviated as CSRF or XSRF, is a type of malicious exploit of a website or web application where unauthorized commands are submitted from a user that the web application trusts. There are many ways in which a malicious website can transmit such commands; specially-crafted image tags, hidden forms, and JavaScript fetch or XMLHttpRequests, for example, can all work without the user's interaction or knowledge. Unlike cross-site scripting (XSS), which exploits the trust a user has for a particular site, CSRF exploits the trust that a site has in a user's browser. In a CSRF attack, an innocent end user is tricked by an attacker into submitting a web request that they did not intend. This may cause actions to be performed on the website that can include inadvertent client or server data leakage, change of session state, or manipulation of an end user's account. Angular provides built-in protection against CSRF attacks through the `HttpClientXsrfModule` module. This module automatically adds a token to outgoing requests and validates it on the server side.
Visit the following resources to learn more:
- [@official@Angular Official Docs - Cross Site Request Forgery](https://angular.dev/best-practices/security#cross-site-request-forgery)
- [@official@HttpClientXsrfModule](https://angular.dev/api/common/http/HttpClientXsrfModule)
- [@video@Configure the CSRF Protection With Spring Security 6 and Angular](https://www.youtube.com/watch?v=tgjLsEmxcuY)
- [@video@Angular security - CSRF prevention using Double Submit Cookie](https://www.youtube.com/watch?v=lZfF4MOTeNM)
# Cross-site Request Forgery

View File

@@ -1,9 +1 @@
# Cross-site Script Inclusion
Cross-site script inclusion, also known as JSON vulnerability, can allow an attacker's website to read data from a JSON API. The attack works on older browsers by overriding built-in JavaScript object constructors, and then including an API URL using a `<script>` tag. Angular's HttpClient library recognizes this convention and automatically strips the string ")]}',\n" from all responses before further parsing.
Visit the following resources to learn more:
- [@official@Angular Official Docs - Cross Site Script Inclusion](https://angular.dev/best-practices/security#cross-site-script-inclusion-xssi)
- [@article@XSSI Cross Site Script Inclusion](https://book.hacktricks.xyz/pentesting-web/xssi-cross-site-script-inclusion)
- [@article@Testing for Cross Site Script Inclusion](https://owasp.org/www-project-web-security-testing-guide/v41/4-Web_Application_Security_Testing/11-Client_Side_Testing/13-Testing_for_Cross_Site_Script_Inclusion)
# Cross-site Script Inclusion

View File

@@ -1,10 +1 @@
# Debugging Tests
If your tests aren't working as you expect them to, you can inspect and debug them in the browser. Be sure to set breakpoints to track your application's execution.
Visit the following resources to learn more:
- [@official@Angular Official Docs - Debugging tests](https://angular.dev/guide/testing/debugging)
- [@official@Angular Official Docs - Devtools](https://angular.dev/tools/devtools)
- [@video@Debug Like a Pro: Essential Breakpoint Techniques in Angular](https://www.youtube.com/watch?v=Be9Q1cchurQ)
- [@video@Debug Angular 17 Code in VS Code with Break Points and Extensions](https://www.youtube.com/watch?v=r50UXhT9hc0)
# Debugging Tests

Some files were not shown because too many files have changed in this diff Show More