Compare commits

...

86 Commits

Author SHA1 Message Date
Arik Chakma
e6cbf55a38 feat: add more questions 2024-01-19 23:41:49 +06:00
Arik Chakma
d66d4bcb8a feat: add nodejs questions 2024-01-19 01:01:38 +06:00
Alvin
932896c3af fix: replace broken link to complete java course (#5049) 2024-01-18 23:08:14 +06:00
Kamran Ahmed
1539c6ccaf Update markdown 2024-01-18 21:15:50 +05:00
Kamran Ahmed
84aa35cdec Merge branch 'master' of github.com:kamranahmedse/developer-roadmap 2024-01-18 21:05:38 +05:00
Kamran Ahmed
b6a852b29b Add a guide for backend languages 2024-01-18 21:00:33 +05:00
Marco Malvicini
2d2f670153 typo-fix: typescript roadmap update 108-enum.md (#5030) 2024-01-18 11:57:33 +05:00
Komal Shehzadi
5cf7aa340f Correction in as type operator example (#5017) 2024-01-11 11:11:38 +05:00
Selva Muthu Kumaran Boopalan
601d21ca9d doc: add new AWS resources (#4954)
* devops-roadmap-aws

devops-roadmap-aws-newlink-provided
fixes: #4838

* Update src/data/roadmaps/devops/content/107-cloud-providers/100-aws.md

---------

Co-authored-by: Arik Chakma <arikchangma@gmail.com>
2024-01-09 18:16:21 +06:00
Shreyash
a5527dd872 fix: react-native pdf (#4645)
The previous pdf contained 2 pages - 1st page for c++ and 2nd for react-native. Fixed this by deleting the first page of the pdf.
2024-01-09 18:00:02 +06:00
Ahmed Abdul Saad
4d6d943b4e doc: fix typo (#4889)
typo fix
2024-01-09 17:39:38 +06:00
Randil Tharusha
85214da400 doc: add javascript testing youtube video tutorial (#4926) 2024-01-09 17:15:07 +06:00
Tobiáš Smolný
46eb27a810 doc: add new resources (#5002) 2024-01-09 17:00:57 +06:00
Umut
e47bd63cc9 fix: typo (#4900)
There was a duplicate "the" word in the Sentiment Analysis entry. I fixed it.
2024-01-09 14:51:08 +06:00
Agustin Velez
d314f3d8c1 doc: add resources for variable and data types (#4948)
Add links for variables and data types from The Book (Official docs)
2024-01-09 14:49:51 +06:00
Dominik Galiev
52fdd8f07d fix: missing syntax (#5005) 2024-01-09 14:44:24 +06:00
dev-aly3n
22f59c66f0 fix: replace broken link with a valid one in frontend performance (#5001) 2024-01-09 14:15:17 +06:00
dev-aly3n
4a862241d3 fix: markdown missing closing parenthesis for link (#4999) 2024-01-09 14:13:38 +06:00
Sonvir
b1fdc7ff49 fix: update enable http reference url (#4922)
fix #4862

Co-authored-by: sonvir249 <39142-sonvir249@users.noreply.drupalcode.org>
2024-01-09 14:09:06 +06:00
dev-aly3n
445bdabde5 fix: change the broken link to a valid resource (#4970) 2024-01-09 00:03:55 +06:00
ArianHamdi
c46b4220a7 fix: change 'decentralised' to 'decentralized' (#4967) 2024-01-09 00:02:45 +06:00
Khalil Habib Shariff
cdcdfc4973 doc: clarity about flask (#4973)
added clarity about flask features
2024-01-08 23:59:44 +06:00
John Moore
d4b4b3c55c fix: grammars (#4989)
Proper and consistent styling
2024-01-08 23:49:58 +06:00
Samuel Mensah Boafo
2c0ebe4209 fix: javascript versions (#4992)
* Update 102-javascript-versions.md

* Update 102-javascript-versions.md

* fix: add link text

---------

Co-authored-by: Arik Chakma <arikchangma@gmail.com>
2024-01-08 23:35:46 +06:00
Dhruv Kumar
c51438142c fix : year from 2023 to 2024 (#4979) 2024-01-08 23:29:49 +06:00
P J Sahrudh
d5a47b79db fix: try, catch, throw broken video link (#4961)
* Update index.md

Removed 'try, catch, throw" video as it is broken.

* Update src/data/roadmaps/javascript/content/107-javascript-control-flow/100-exception-handling/index.md

---------

Co-authored-by: Arik Chakma <arikchangma@gmail.com>
2024-01-03 17:24:04 +06:00
Young
ca2a75537e fix: npm broken links (#4968)
The old link has expired 404

Co-authored-by: Young <yunyg@qq.com>
2024-01-03 17:19:02 +06:00
mshafiqyajid
f62faf214c fix: broken superagent official website link (#4942) 2023-12-31 07:28:42 +06:00
Muhammad Khalid
00b9630669 typo: followinw to following (#4943) 2023-12-31 07:24:07 +06:00
Rishiraj S
49ba524c15 fix: remove deprecated remove method (#4924) 2023-12-28 19:40:26 +06:00
ArianHamdi
d4436e8a8f fix: introduction to blockchain links (#4935)
* fix: introduction to blockchain links

* fix: Smart Contracts Introduction link
2023-12-28 19:37:46 +06:00
Arik Chakma
e0b3209dc4 Fix markdown link issue (#4849) 2023-12-25 21:21:52 +05:00
Olivier Tassinari
cf5dd19652 Update Material UI guide to v5 (#4588)
* Update Material UI guide to v5

* keep in sycn
2023-12-24 19:02:16 +06:00
Kamran Ahmed
16680e2629 Update dependencies 2023-12-24 16:20:12 +05:00
Selva Muthu Kumaran
b9b12333cb Fix broken Youtube link (#4888)
devops-roadmap-networking-protocols-sshfullgu :ide-new-videolink-provided
2023-12-19 20:33:47 +06:00
lucasffa
8a9bb60211 Fix link text typo (#4873)
There was a typo
2023-12-18 23:17:28 +06:00
Yusuf Seward
2c6bef62b2 Fix Content Typo (#3525) 2023-12-13 05:51:14 +06:00
steph
efb7e13f7d Fix Resource Typo (#4535) 2023-12-13 05:50:14 +06:00
Sarah Mak
b34c7eff65 Fix "discuss" typo (#4524) 2023-12-13 05:47:41 +06:00
bivashy
15c43fda5d Fix Broken Link and Typo (#4763)
* Fix typo in angular/rxjs-basics/marble-diagrams

* Remove Marble Diagrams broken link
2023-12-13 05:46:42 +06:00
rasalagean
b38f34a722 Fix Angular Roadmap Type Guard video URL (#4800) 2023-12-13 05:38:29 +06:00
Abderrahmane Larchi
f1780fabda Update Duplicate Link (#4819)
The first link now 'Control Flow Statements' just sends to the the third link for 'Branches', so it's just a duplicate now.
2023-12-13 05:36:03 +06:00
Simon
5362a64c29 Fix Minor Punctuations (#4826) 2023-12-13 05:34:55 +06:00
Sherkhan Azimov
720809f139 Fix Service Discovery Link (#4827) 2023-12-13 05:32:58 +06:00
Mahyar
5b03601aa2 Fix Polynomial Time Complexity (#4836) 2023-12-13 05:31:22 +06:00
Wasif
90df308751 Fix Content Heading (#4850)
Fixing Typos: Heading was wrong.
2023-12-13 05:27:33 +06:00
Sepehr Safari
3c0545e54f Fix Heap Typo (#4851) 2023-12-13 05:26:19 +06:00
Kamran Habib
4eb145dff4 Fix Content Grammar Typo (#4854)
I made a slight modification to improve the clarity of the sentence.
Specifically, I changed:

"Make sure to follow the instructions provided by the editor's documentation to set up C++ correctly."

to:

"Make sure to follow the instructions provided in the editor's documentation to set up C++ correctly."

This change maintains the same meaning but improves the flow of the sentence.
2023-12-13 05:25:38 +06:00
HlexNC
966d5fedb5 Update database section to focus on scaling databases (#4843) 2023-12-11 00:39:45 +00:00
Drew Rodrigues
243778cf11 Update session-based-authentication.md (#4844) 2023-12-11 00:39:10 +00:00
Kamran Ahmed
9c9c59911b Update backend roadmap JSON 2023-12-09 20:15:38 +00:00
Kamran Ahmed
7a93301b5b Upgrade dependencies 2023-12-09 20:08:12 +00:00
Kamran Ahmed
aa056c1da8 Update backend roadmap 2023-12-09 20:02:05 +00:00
Kamran Ahmed
13d1879977 Add embed roadmap functionalityg 2023-12-05 22:58:46 +00:00
Hardik
aca3163ba9 Flutter : update 100-material-widgets.md (#4824)
'RaisedButton' is deprecated and shouldn't be used. It is replaced by ElevatedButton
2023-12-05 21:36:19 +06:00
Kamran Ahmed
5e80d9d4d8 Add embed functionality 2023-12-05 15:32:17 +00:00
Kamran Ahmed
0fc28c482a Add content for AWS roadmap 2023-11-29 14:53:08 +00:00
Kamran Ahmed
837d2ac782 Add roadmap dirs for AWS 2023-11-29 14:09:49 +00:00
Kamran Ahmed
68c62bacc2 Add AWS roadmap 2023-11-29 05:31:41 +00:00
Jakub Kaźmierczak
720438e619 Add DDD resources (#4765) 2023-11-27 23:11:14 +00:00
Selva Muthu Kumaran
3afab1aa70 Add resource for DDOS (#4776)
cyber-security-ddos-link-updated
2023-11-27 23:10:14 +00:00
Selva Muthu Kumaran
f40585f992 Remove redundant link (#4777)
roadmap-javascript-built-in-object-redundant-link
fixes: #4758
2023-11-27 23:09:47 +00:00
Selva Muthu Kumaran
9232d03e24 Add resource for np completness (#4778)
roadmap-computer-science-np-complete-new-video-link-provided
fixes: #4731
2023-11-27 23:09:19 +00:00
Jakub Kaźmierczak
01cb4b5131 Add backpressure resource (#4779) 2023-11-27 23:08:46 +00:00
Yoandre Saavedra Gonzalez
50f02b504a Update Top Python Asynchronous Web Frameworks (#4766)
The number changed from 5 to 9 in the original article.
2023-11-27 01:42:51 +06:00
Jakub Kaźmierczak
2d12bffe46 Update backend service mesh description (#4752) 2023-11-25 01:13:29 +00:00
Rishi
3b1762cd91 Update Next.js resource (#4750)
Updated to latest video of NextJS from freecodecamp in Forntend RoadMap
2023-11-23 20:20:58 +00:00
Rachit Agrawal
d9be6e3c8b Fix invalid URL (#4747) 2023-11-23 20:20:24 +00:00
Kamran Ahmed
b65328ebc9 Add zilliz logo 2023-11-23 20:19:29 +00:00
Kamran Ahmed
5da5924b6c Update embed logo 2023-11-22 14:06:58 +00:00
Kamran Ahmed
b35a169315 Allow embedding of roadmaps 2023-11-22 13:53:30 +00:00
omkarl08
9d05c64f50 Add course for linear algebra (#4703)
* Update 100-linear-algebra.md

Kimberly Brehm's Linear Algebra Course

> Matrices: Properties, operations, and applications.
> Determinants: Role in system solvability and transformations.
> Vectors: Geometric interpretation and relevance in 
    transformations.

Eigenvalues & Eigenvectors: Stability and system analysis.
This course lays a solid foundation for game development. Matrices and vectors are core elements in creating graphics, handling transformations, and optimizing game performance. Understanding determinants aids in solving complex problems, while eigenvalues/eigenvectors are crucial for stability in game mechanics. Focus on matrices, vectors, and transformations for practical game design applications.

* Update src/data/roadmaps/game-developer/content/101-game-mathematics/100-linear-algebra.md

---------

Co-authored-by: Kamran Ahmed <kamranahmed.se@gmail.com>
2023-11-16 19:33:47 +00:00
Kaya-Sem
e94296cdd4 Update 101-app-shortcuts.md (#4705)
Removed unnecessary chatgpt line.
2023-11-16 19:32:37 +00:00
Max Mynter
7a4796508d Add Fullstack Deep Learning to MLOps (#4698) 2023-11-15 23:06:09 +00:00
Kamran Ahmed
e0f5d6f436 Update contribution functionality 2023-11-15 02:58:56 +00:00
Kamran Ahmed
d103bc629c Topic links contribution functionality 2023-11-15 02:46:45 +00:00
Kamran Ahmed
cb9943191e Add axum 2023-11-14 20:20:38 +00:00
Kamran Ahmed
eaa567dfe0 Add link to rust roadmap 2023-11-14 18:53:35 +00:00
Kamran Ahmed
277713e16b Add rust roadmap 2023-11-14 18:35:14 +00:00
Kamran Ahmed
5ed49b965c Add rust roadmap 2023-11-14 18:19:07 +00:00
Ebenezer Adeoye
a27aaf6e2d Fixed the links not working (#4677) 2023-11-12 18:50:59 +00:00
Kamran Ahmed
be02cc59ea Add favorite functionality 2023-11-12 18:50:05 +00:00
Abdelrhman Kamal
068847af08 Abdelrhman: Fix best practices articles (#4680)
* Fix gtx-trans close sidepanel

* reset the package-lock.json file

* Install the CodeSee workflow. Learn more at https://docs.codesee.io

* Fix Best Practcies roadmaps articels

* Restore files

---------

Co-authored-by: codesee-maps[bot] <86324825+codesee-maps[bot]@users.noreply.github.com>
2023-11-12 18:37:31 +00:00
Kamran Ahmed
c6c91ef8fe UI fix for friends page 2023-11-09 21:40:51 +00:00
Kamran Ahmed
8fb3e7983b Partial usage in the topics 2023-11-09 21:36:58 +00:00
Kamran Ahmed
80ec1a1c4b Fix images not working in latest astro (#4676)
* Fix respond invite

* Team roadmap icon fix

* Personal roadmap list and empty friends

* Fix invite friend

* Fix user progress modal

* Friends and notification pages

* Friends and notification pages

* Update

* Fix progress modal

---------

Co-authored-by: Arik Chakma <arikchangma@gmail.com>
2023-11-09 21:32:46 +00:00
403 changed files with 28729 additions and 11732 deletions

View File

@@ -22,48 +22,48 @@
"test:e2e": "playwright test"
},
"dependencies": {
"@astrojs/react": "^3.0.4",
"@astrojs/react": "^3.0.8",
"@astrojs/sitemap": "^3.0.3",
"@astrojs/tailwind": "^5.0.2",
"@fingerprintjs/fingerprintjs": "^4.1.0",
"@astrojs/tailwind": "^5.0.4",
"@fingerprintjs/fingerprintjs": "^4.2.1",
"@nanostores/react": "^0.7.1",
"@types/react": "^18.2.37",
"@types/react-dom": "^18.2.15",
"astro": "^3.5.0",
"@types/react": "^18.2.45",
"@types/react-dom": "^18.2.18",
"astro": "^4.0.7",
"astro-compress": "^2.2.3",
"clsx": "^2.0.0",
"dracula-prism": "^2.1.13",
"jose": "^5.1.0",
"jose": "^5.1.3",
"js-cookie": "^3.0.5",
"lucide-react": "^0.292.0",
"nanoid": "^5.0.3",
"nanostores": "^0.9.4",
"lucide-react": "^0.300.0",
"nanoid": "^5.0.4",
"nanostores": "^0.9.5",
"node-html-parser": "^6.1.11",
"npm-check-updates": "^16.14.6",
"npm-check-updates": "^16.14.12",
"prismjs": "^1.29.0",
"react": "^18.2.0",
"react-confetti": "^6.1.0",
"react-dom": "^18.2.0",
"reactflow": "^11.9.4",
"reactflow": "^11.10.1",
"rehype-external-links": "^3.0.0",
"roadmap-renderer": "^1.0.6",
"slugify": "^1.6.6",
"tailwind-merge": "^2.0.0",
"tailwindcss": "^3.3.5",
"zustand": "^4.4.6"
"tailwind-merge": "^2.2.0",
"tailwindcss": "^3.4.0",
"zustand": "^4.4.7"
},
"devDependencies": {
"@playwright/test": "^1.39.0",
"@playwright/test": "^1.40.1",
"@tailwindcss/typography": "^0.5.10",
"@types/js-cookie": "^3.0.6",
"@types/prismjs": "^1.26.3",
"csv-parser": "^3.0.0",
"gh-pages": "^6.0.0",
"gh-pages": "^6.1.1",
"js-yaml": "^4.1.0",
"markdown-it": "^13.0.2",
"openai": "^4.17.1",
"prettier": "^3.0.3",
"prettier-plugin-astro": "^0.12.1",
"prettier-plugin-tailwindcss": "^0.5.7"
"markdown-it": "^14.0.0",
"openai": "^4.24.1",
"prettier": "^3.1.1",
"prettier-plugin-astro": "^0.12.2",
"prettier-plugin-tailwindcss": "^0.5.9"
}
}

1794
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

0
public/manifest/apple-touch-icon.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

0
public/manifest/favicon.ico Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

0
public/manifest/icon152.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

0
public/manifest/icon16.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 123 B

After

Width:  |  Height:  |  Size: 123 B

0
public/manifest/icon196.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

0
public/manifest/icon32.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 267 B

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

Binary file not shown.

BIN
public/roadmaps/aws.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 KiB

BIN
public/roadmaps/rust.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 KiB

View File

@@ -53,6 +53,7 @@ Here is the list of available roadmaps with more being actively worked upon.
- [Android Roadmap](https://roadmap.sh/android)
- [Flutter Roadmap](https://roadmap.sh/flutter)
- [Go Roadmap](https://roadmap.sh/golang)
- [Rust Roadmap](https://roadmap.sh/rust)
- [Java Roadmap](https://roadmap.sh/java)
- [Spring Boot Roadmap](https://roadmap.sh/spring-boot)
- [Design System Roadmap](https://roadmap.sh/design-system)

View File

@@ -59,9 +59,9 @@ function writeTopicContent(currTopicUrl) {
const roadmapTitle = roadmapId.replace(/-/g, ' ');
let prompt = `I am reading a guide about "${roadmapTitle}". I am on the topic "${parentTopic}". I want to know more about "${childTopic}". Write me a brief paragraph for that. Content should be in markdown. I already know the benefits of each so do not add benefits in the output.`;
let prompt = `I am reading a guide about "${roadmapTitle}". I am on the topic "${parentTopic}". I want to know more about "${childTopic}". Write me a brief paragraph for that. Your output should be strictly markdown. Do not include anything other than the description in your output. I already know the benefits of each so do not add benefits in the output.`;
if (!childTopic) {
prompt = `I am reading a guide about "${roadmapTitle}". I am on the topic "${parentTopic}". I want to know more about "${parentTopic}". Write me a brief paragraph for that. Content should be in markdown. I already know the benefits of each so do not add benefits in the output.`;
prompt = `I am reading a guide about "${roadmapTitle}". I am on the topic "${parentTopic}". I want to know more about "${parentTopic}". Write me a brief paragraph for that. Your output should be strictly markdown. Do not include anything other than the description in your output. I already know the benefits of each so do not add benefits in the output.`;
}
console.log(`Generating '${childTopic || parentTopic}'...`);

View File

@@ -1,14 +1,11 @@
import RoadmapIcon from '../../icons/roadmap.svg';
import { RoadmapIcon } from "../ReactIcons/RoadmapIcon";
export function EmptyActivity() {
return (
<div className="rounded-md">
<div className="flex flex-col items-center p-7 text-center">
<img
alt="no roadmaps"
src={RoadmapIcon.src}
className="mb-2 w-[60px] h-[60px] sm:h-[120px] sm:w-[120px] opacity-10"
/>
<RoadmapIcon className="mb-2 w-[60px] h-[60px] sm:h-[120px] sm:w-[120px] opacity-10" />
<h2 className="text-lg sm:text-xl font-bold">No Progress</h2>
<p className="my-1 sm:my-2 max-w-[400px] text-gray-500 text-sm sm:text-base">
Progress will appear here as you start tracking your{' '}

View File

@@ -1,4 +1,4 @@
import ChevronDownIcon from '../../icons/chevron-down.svg';
import { ChevronDownIcon } from '../ReactIcons/ChevronDownIcon';
type NotDropdownProps = {
onClick: () => void;
@@ -37,11 +37,7 @@ export function NotDropdown(props: NotDropdownProps) {
</div>
)}
<img
alt={singularName}
src={ChevronDownIcon.src}
className={'relative top-[1px] h-[17px] w-[17px] opacity-40'}
/>
<ChevronDownIcon className="relative top-[1px] h-[17px] w-[17px] opacity-40" />
</div>
);
}

View File

@@ -53,14 +53,20 @@ export type GetRoadmapResponse = RoadmapDocument & {
export function hideRoadmapLoader() {
const loaderEl = document.querySelector(
'[data-roadmap-loader]'
'[data-roadmap-loader]',
) as HTMLElement;
if (loaderEl) {
loaderEl.remove();
}
}
export function CustomRoadmap() {
type CustomRoadmapProps = {
isEmbed?: boolean;
};
export function CustomRoadmap(props: CustomRoadmapProps) {
const { isEmbed = false } = props;
const { id, secret } = getUrlParams() as { id: string; secret: string };
const [isLoading, setIsLoading] = useState(true);
@@ -71,14 +77,15 @@ export function CustomRoadmap() {
setIsLoading(true);
const roadmapUrl = new URL(
`${import.meta.env.PUBLIC_API_URL}/v1-get-roadmap/${id}`
`${import.meta.env.PUBLIC_API_URL}/v1-get-roadmap/${id}`,
);
if (secret) {
roadmapUrl.searchParams.set('secret', secret);
}
const { response, error } = await httpGet<GetRoadmapResponse>(
roadmapUrl.toString()
roadmapUrl.toString(),
);
if (error || !response) {
@@ -95,7 +102,10 @@ export function CustomRoadmap() {
}
async function trackVisit() {
if (!isLoggedIn()) return;
if (!isLoggedIn() || isEmbed) {
return;
}
await httpPost(`${import.meta.env.PUBLIC_API_URL}/v1-visit`, {
resourceId: id,
resourceType: 'roadmap',
@@ -119,9 +129,9 @@ export function CustomRoadmap() {
return (
<>
<RoadmapHeader />
<FlowRoadmapRenderer roadmap={roadmap!} />
<TopicDetail canSubmitContribution={false} />
{!isEmbed && <RoadmapHeader />}
<FlowRoadmapRenderer isEmbed={isEmbed} roadmap={roadmap!} />
<TopicDetail isEmbed={isEmbed} canSubmitContribution={false} />
</>
);
}

View File

@@ -0,0 +1,81 @@
import { useStore } from '@nanostores/react';
import { Check, Copy } from 'lucide-react';
import { Modal } from '../Modal';
import { useToast } from '../../hooks/use-toast';
import { useCopyText } from '../../hooks/use-copy-text';
import { currentRoadmap, isCurrentRoadmapPersonal } from '../../stores/roadmap';
import { cn } from '../../lib/classname.ts';
type ShareRoadmapModalProps = {
onClose: () => void;
};
export function EmbedRoadmapModal(props: ShareRoadmapModalProps) {
const { onClose } = props;
const toast = useToast();
const $currentRoadmap = useStore(currentRoadmap);
const $isCurrentRoadmapPersonal = useStore(isCurrentRoadmapPersonal);
const roadmapId = $currentRoadmap?._id!;
const { copyText, isCopied } = useCopyText();
const isDev = import.meta.env.DEV;
const baseUrl = isDev ? 'http://localhost:3000' : 'https://roadmap.sh';
const embedHtml = `<iframe src="${baseUrl}/r/embed?id=${roadmapId}" width="100%" height="500px" frameBorder="0"\n></iframe>`;
return (
<Modal onClose={onClose} wrapperClassName={'max-w-[500px]'}>
<div className="p-4 pb-0">
<h1 className="text-xl font-semibold leading-5 text-gray-900">
Embed Roadmap
</h1>
</div>
<div className="px-4 pt-3">
<p className={'mb-2 text-sm text-gray-500'}>
Copy the following HTML code and paste it into your website.
</p>
<input
type="text"
value={embedHtml}
readOnly={true}
onClick={(e) => {
e.currentTarget.select();
copyText(embedHtml);
}}
className="w-full resize-none rounded-md border bg-gray-50 p-2 text-sm"
/>
</div>
<div className="flex items-center justify-between px-4 pb-4 pt-2">
<button
className={cn(
'flex h-9 w-full items-center justify-center rounded-md border border-transparent px-4 py-2 text-sm font-medium text-white outline-none',
{
'bg-green-500 hover:bg-green-600 focus:bg-green-600': isCopied,
'bg-gray-900 hover:bg-gray-800 focus:bg-gray-800': !isCopied,
},
)}
onClick={() => {
copyText(embedHtml);
}}
>
{isCopied ? (
<>
<Check size={14} className="mr-2 stroke-[2.5]" />
Copied
</>
) : (
<>
<Copy size={14} className="mr-2 stroke-[2.5]" />
Copy Link
</>
)}
</button>
</div>
</Modal>
);
}

View File

@@ -1,26 +1,27 @@
import { ReadonlyEditor } from '../../../editor/readonly-editor';
import type { RoadmapDocument } from './CreateRoadmap/CreateRoadmapModal';
import {
renderResourceProgress,
updateResourceProgress,
type ResourceProgressType,
renderTopicProgress,
refreshProgressCounters,
renderResourceProgress,
renderTopicProgress,
type ResourceProgressType,
updateResourceProgress,
} from '../../lib/resource-progress';
import { pageProgressMessage } from '../../stores/page';
import { useToast } from '../../hooks/use-toast';
import type { Node } from 'reactflow';
import { useCallback, type MouseEvent, useMemo, useState, useRef } from 'react';
import { type MouseEvent, useCallback, useRef, useState } from 'react';
import { EmptyRoadmap } from './EmptyRoadmap';
import { cn } from '../../lib/classname';
import { totalRoadmapNodes } from '../../stores/roadmap.ts';
type FlowRoadmapRendererProps = {
isEmbed?: boolean;
roadmap: RoadmapDocument;
};
export function FlowRoadmapRenderer(props: FlowRoadmapRendererProps) {
const { roadmap } = props;
const { roadmap, isEmbed = false } = props;
const roadmapId = String(roadmap._id!);
const [hideRenderer, setHideRenderer] = useState(false);
@@ -32,6 +33,10 @@ export function FlowRoadmapRenderer(props: FlowRoadmapRendererProps) {
topicId: string,
newStatus: ResourceProgressType,
) {
if (isEmbed) {
return;
}
pageProgressMessage.set('Updating progress');
updateResourceProgress(
{

View File

@@ -14,11 +14,11 @@ import {
type AllowedRoadmapVisibility,
type RoadmapDocument,
} from './CreateRoadmap/CreateRoadmapModal';
import RoadmapIcon from '../../icons/roadmap.svg';
import { PersonalRoadmapActionDropdown } from './PersonalRoadmapActionDropdown';
import type { GetRoadmapListResponse } from './RoadmapListPage';
import { useState, type Dispatch, type SetStateAction } from 'react';
import { ShareOptionsModal } from '../ShareOptions/ShareOptionsModal';
import {RoadmapIcon} from "../ReactIcons/RoadmapIcon.tsx";
type PersonalRoadmapListType = {
roadmaps: GetRoadmapListResponse['personalRoadmaps'];
@@ -91,11 +91,8 @@ export function PersonalRoadmapList(props: PersonalRoadmapListType) {
if (roadmapList.length === 0) {
return (
<div className="flex flex-col items-center p-4 py-20">
<img
alt="roadmap"
src={RoadmapIcon.src}
className="mb-4 h-24 w-24 opacity-10"
/>
<RoadmapIcon className="mb-4 h-24 w-24 opacity-10" />
<h3 className="mb-1 text-2xl font-bold text-gray-900">No roadmaps</h3>
<p className="text-base text-gray-500">
Create a roadmap to get started

View File

@@ -11,6 +11,7 @@ import { RoadmapActionButton } from './RoadmapActionButton';
import { Lock, Shapes } from 'lucide-react';
import { Modal } from '../Modal';
import { ShareSuccess } from '../ShareOptions/ShareSuccess';
import { ShareRoadmapButton } from '../ShareRoadmapButton.tsx';
type RoadmapHeaderProps = {};
@@ -44,11 +45,11 @@ export function RoadmapHeader(props: RoadmapHeaderProps) {
{
resourceId: roadmapId,
resourceType: 'roadmap',
}
},
));
} else {
({ error, response } = await httpDelete<TeamResourceConfig>(
`${baseApiUrl}/v1-delete-roadmap/${roadmapId}`
`${baseApiUrl}/v1-delete-roadmap/${roadmapId}`,
));
}
@@ -119,7 +120,7 @@ export function RoadmapHeader(props: RoadmapHeaderProps) {
</div>
<div className="flex justify-between gap-2 sm:gap-0">
<div className="flex gap-1 sm:gap-2">
<div className="flex justify-stretch gap-1 sm:gap-2">
<a
href="/roadmaps"
className="rounded-md bg-gray-500 px-3 py-1.5 text-xs font-medium text-white hover:bg-gray-600 sm:text-sm"
@@ -128,14 +129,12 @@ export function RoadmapHeader(props: RoadmapHeaderProps) {
&larr;<span className="hidden sm:inline">&nbsp;All Roadmaps</span>
</a>
<button
data-guest-required
data-popup="login-popup"
className="inline-flex hidden items-center justify-center rounded-md bg-yellow-400 px-3 py-1.5 text-xs font-medium hover:bg-yellow-500 sm:text-sm"
aria-label="Subscribe for Updates"
>
<span className="ml-2">Subscribe</span>
</button>
<ShareRoadmapButton
roadmapId={roadmapId!}
description={description!}
pageUrl={`https://roadmap.sh/r?id=${roadmapId}`}
allowEmbed={true}
/>
</div>
<div className="flex items-center gap-2">
{$canManageCurrentRoadmap && (
@@ -162,9 +161,9 @@ export function RoadmapHeader(props: RoadmapHeaderProps) {
)}
<a
href={`${import.meta.env.PUBLIC_EDITOR_APP_URL}/${
$currentRoadmap?._id
}`}
href={`${
import.meta.env.PUBLIC_EDITOR_APP_URL
}/${$currentRoadmap?._id}`}
target="_blank"
className="inline-flex items-center justify-center rounded-md border border-gray-300 bg-white py-1.5 pl-2 pr-2 text-xs font-medium text-black hover:border-gray-300 hover:bg-gray-300 sm:px-3 sm:text-sm"
>
@@ -183,7 +182,7 @@ export function RoadmapHeader(props: RoadmapHeaderProps) {
<RoadmapActionButton
onDelete={() => {
const confirmation = window.confirm(
'Are you sure you want to delete this roadmap?'
'Are you sure you want to delete this roadmap?',
);
if (!confirmation) {

View File

@@ -12,7 +12,10 @@ export function SkeletonRoadmapHeader() {
</div>
<div className="flex justify-between gap-2 sm:gap-0">
<div className="h-7 w-[35.04px] animate-pulse rounded-md bg-gray-300 sm:h-8 sm:w-32" />
<div className='flex gap-1 sm:gap-2'>
<div className="h-7 w-[35.04px] animate-pulse rounded-md bg-gray-300 sm:h-8 sm:w-32" />
<div className="h-7 w-[35.04px] animate-pulse rounded-md bg-gray-300 sm:h-8 sm:w-[85px]" />
</div>
<div className="flex items-center gap-2">
<div className="h-7 w-[60.52px] animate-pulse rounded-md bg-gray-300 sm:h-8 sm:w-[139.71px]" />
<div className="h-7 w-[71.48px] animate-pulse rounded-md bg-gray-300 sm:h-8 sm:w-[100.34px]" />

View File

@@ -1,6 +1,5 @@
import UserPlusIcon from '../../icons/user-plus.svg';
import CopyIcon from '../../icons/copy.svg';
import { useCopyText } from '../../hooks/use-copy-text';
import { CopyIcon, UserPlus2 } from 'lucide-react';
type EmptyFriendsProps = {
befriendUrl: string;
@@ -13,14 +12,12 @@ export function EmptyFriends(props: EmptyFriendsProps) {
return (
<div className="rounded-md">
<div className="mx-auto flex flex-col items-center p-7 text-center">
<img
alt="no friends"
src={UserPlusIcon.src}
className="mb-2 h-[60px] w-[60px] opacity-10 sm:h-[120px] sm:w-[120px]"
/>
<UserPlus2 className="mb-2 h-[60px] w-[60px] opacity-10 sm:h-[120px] sm:w-[120px]" />
<h2 className="text-lg font-bold sm:text-xl">Invite your Friends</h2>
<p className="mb-4 mt-1 max-w-[400px] text-sm leading-relaxed text-gray-500">
Share the unique link below with your friends to track their skills and progress.
Share the unique link below with your friends to track their skills
and progress.
</p>
<div className="flex w-full max-w-[352px] items-center justify-center gap-2 rounded-lg border-2 p-1 text-sm">
@@ -44,7 +41,8 @@ export function EmptyFriends(props: EmptyFriendsProps) {
copyText(befriendUrl);
}}
>
<img src={CopyIcon.src} className="h-4 w-4" alt="Invite Friends" />
<CopyIcon className="mr-1 h-4 w-4" />
{isCopied ? 'Copied' : 'Copy'}
</button>
</div>

View File

@@ -7,10 +7,10 @@ import type { FriendshipStatus } from '../Befriend';
import { useToast } from '../../hooks/use-toast';
import { EmptyFriends } from './EmptyFriends';
import { FriendProgressItem } from './FriendProgressItem';
import UserIcon from '../../icons/user.svg';
import { UserProgressModal } from '../UserProgress/UserProgressModal';
import { InviteFriendPopup } from './InviteFriendPopup';
import { UserCustomProgressModal } from '../UserProgress/UserCustomProgressModal';
import { UserIcon } from 'lucide-react';
type FriendResourceProgress = {
updatedAt: string;
@@ -64,7 +64,7 @@ export function FriendsPage() {
async function loadFriends() {
const { response, error } = await httpGet<ListFriendsResponse>(
`${import.meta.env.PUBLIC_API_URL}/v1-list-friends`
`${import.meta.env.PUBLIC_API_URL}/v1-list-friends`,
);
if (error || !response) {
@@ -89,15 +89,15 @@ export function FriendsPage() {
const befriendUrl = `${baseUrl}/befriend?u=${user?.id}`;
const selectedGroupingType = groupingTypes.find(
(grouping) => grouping.value === selectedGrouping
(grouping) => grouping.value === selectedGrouping,
);
const filteredFriends = friends.filter((friend) =>
selectedGroupingType?.statuses.includes(friend.status)
const filteredFriends = friends.filter(
(friend) => selectedGroupingType?.statuses.includes(friend.status),
);
const receivedRequests = friends.filter(
(friend) => friend.status === 'received'
(friend) => friend.status === 'received',
);
if (isLoading) {
@@ -203,11 +203,8 @@ export function FriendsPage() {
{filteredFriends.length === 0 && (
<div className="flex flex-col items-center justify-center py-12">
<img
src={UserIcon.src}
alt="Empty Friends"
className="mb-3 w-12 opacity-20"
/>
<UserIcon size={'60px'} className="mb-3 w-12 opacity-20" />
<h2 className="text-lg font-semibold">
{selectedGrouping === 'active' && 'No friends yet'}
{selectedGrouping === 'sent' && 'No requests sent'}

View File

@@ -1,8 +1,8 @@
import type { MouseEvent } from 'react';
import { useRef } from 'react';
import { useOutsideClick } from '../../hooks/use-outside-click';
import CopyIcon from '../../icons/copy.svg';
import { useCopyText } from '../../hooks/use-copy-text';
import { CopyIcon } from 'lucide-react';
type InviteFriendPopupProps = {
befriendUrl: string;
@@ -54,11 +54,7 @@ export function InviteFriendPopup(props: InviteFriendPopupProps) {
copyText(befriendUrl);
}}
>
<img
src={CopyIcon.src}
className="h-4 w-4"
alt="Invite Friends"
/>
<CopyIcon className="mr-1 h-4 w-4" />
{isCopied ? 'Copied' : 'Copy URL'}
</button>
</div>

View File

@@ -13,7 +13,7 @@ const { frontmatter, id } = guide;
class:list={[
"block no-underline py-2 group text-md items-center text-gray-600 hover:text-blue-600 flex justify-between border-b",
]}
href={`/guides/${id}`}
href={frontmatter.excludedBySlug ? frontmatter.excludedBySlug : `/guides/${id}`}
>
<span class="group-hover:translate-x-2 transition-transform">
{frontmatter.title}

View File

@@ -1,5 +1,5 @@
<div
class='prose-xl prose-blockquote:font-normal prose container prose-code:bg-transparent prose-h2:text-3xl prose-h2:mt-10 prose-h2:mb-3 prose-h3:mt-2 prose-img:mt-1'
class='prose-xl prose-blockquote:font-normal prose container prose-code:bg-transparent prose-h2:text-3xl prose-h2:mt-10 prose-h2:mb-3 prose-h5:font-medium prose-h3:mt-2 prose-img:mt-1'
>
<slot />
</div>

View File

@@ -1,10 +1,10 @@
import { useEffect, useState } from 'react';
import { httpGet, httpPatch, httpPost } from '../../lib/http';
import { httpGet, httpPatch } from '../../lib/http';
import { pageProgressMessage } from '../../stores/page';
import type { TeamMemberDocument } from '../TeamMembers/TeamMembersPage';
import XIcon from '../../icons/close-dark.svg';
import AcceptIcon from '../../icons/accept.svg';
import { useToast } from '../../hooks/use-toast';
import { AcceptIcon } from '../ReactIcons/AcceptIcon.tsx';
import { XIcon } from 'lucide-react';
interface NotificationList extends TeamMemberDocument {
name: string;
@@ -18,7 +18,7 @@ export function NotificationPage() {
const lostNotifications = async () => {
const { error, response } = await httpGet<NotificationList[]>(
`${import.meta.env.PUBLIC_API_URL}/v1-get-invitation-list`
`${import.meta.env.PUBLIC_API_URL}/v1-get-invitation-list`,
);
if (error || !response) {
toast.error(error?.message || 'Something went wrong');
@@ -28,28 +28,37 @@ export function NotificationPage() {
setNotifications(response);
};
async function respondInvitation(status: 'accept' | 'reject', inviteId: string) {
async function respondInvitation(
status: 'accept' | 'reject',
inviteId: string,
) {
setIsLoading(true);
setError('');
const { response, error } = await httpPatch<{ teamId: string }>(
`${import.meta.env.PUBLIC_API_URL}/v1-respond-invite/${inviteId}`, {
status
});
`${import.meta.env.PUBLIC_API_URL}/v1-respond-invite/${inviteId}`,
{
status,
},
);
if (error || !response) {
setError(error?.message || 'Something went wrong')
setIsLoading(false)
setError(error?.message || 'Something went wrong');
setIsLoading(false);
return;
}
if (status === 'accept') {
window.location.href = `/team/progress?t=${response.teamId}`;
} else {
window.dispatchEvent(new CustomEvent('refresh-notification', {
detail: {
count: notifications.length - 1
}
}));
setNotifications(notifications.filter((notification) => notification._id !== inviteId));
window.dispatchEvent(
new CustomEvent('refresh-notification', {
detail: {
count: notifications.length - 1,
},
}),
);
setNotifications(
notifications.filter((notification) => notification._id !== inviteId),
);
setIsLoading(false);
}
}
@@ -66,15 +75,20 @@ export function NotificationPage() {
<h2 className="text-3xl font-bold sm:text-4xl">Notification</h2>
<p className="mt-2 text-gray-400">Manage your notifications</p>
</div>
{
notifications.length === 0 && (
<div className="flex items-center justify-center mt-6">
<p className="text-gray-400">
No notifications, you can <a href="/team/new" className="text-blue-500 underline hover:no-underline">create a team</a> and invite your friends to join.
</p>
</div>
)
}
{notifications.length === 0 && (
<div className="mt-6 flex items-center justify-center">
<p className="text-gray-400">
No notifications, you can{' '}
<a
href="/team/new"
className="text-blue-500 underline hover:no-underline"
>
create a team
</a>{' '}
and invite your friends to join.
</p>
</div>
)}
<div className="space-y-4">
{notifications.map((notification) => (
<div className="flex items-center justify-between rounded-md border p-2">
@@ -86,19 +100,21 @@ export function NotificationPage() {
</div>
</div>
<div className="flex items-center space-x-2">
<button type="button"
<button
type="button"
disabled={isLoading}
className="inline-flex border p-1 rounded hover:bg-gray-50 disabled:opacity-75"
className="inline-flex rounded border p-1 hover:bg-gray-50 disabled:opacity-75"
onClick={() => respondInvitation('accept', notification?._id!)}
>
<img src={AcceptIcon.src} className="h-4 w-4" />
<AcceptIcon className="h-4 w-4" />
</button>
<button type="button"
<button
type="button"
disabled={isLoading}
className="inline-flex border p-1 rounded hover:bg-gray-50 disabled:opacity-75"
className="inline-flex rounded border p-1 hover:bg-gray-50 disabled:opacity-75"
onClick={() => respondInvitation('reject', notification?._id!)}
>
<img alt={'Close'} src={XIcon.src} className="h-4 w-4" />
<XIcon className="h-4 w-4" />
</button>
</div>
</div>

View File

@@ -15,7 +15,7 @@ const { id, title, subtitle } = Astro.props;
<div
id={id}
tabindex='-1'
class='hidden bg-black/50 overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 h-full items-center justify-center popup'
class='hidden bg-black/50 overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-[999] h-full items-center justify-center popup'
>
<div class='relative p-4 w-full max-w-md h-full md:h-auto'>
<div class='relative bg-white rounded-lg shadow popup-body'>

View File

@@ -0,0 +1,24 @@
type AcceptIconProps = {
className?: string;
};
export function AcceptIcon(props: AcceptIconProps) {
const { className } = props;
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="2"
stroke="#000"
className={className}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M4.5 12.75l6 6 9-13.5"
/>
</svg>
);
}

View File

@@ -13,7 +13,7 @@ export function GitHubIcon(props: GitHubIconProps) {
<path
fillRule="evenodd"
d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362l-.08-9.127c-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126l-.08 13.526c0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z"
fill="#24292f"
fill={ className?.indexOf('text-') !== -1 ? 'currentColor' : '#24292f' }
/>
</svg>
);

View File

@@ -1,7 +1,5 @@
import { useEffect, useState } from 'react';
import { httpGet, httpPatch } from '../lib/http';
import BuildingIcon from '../icons/building.svg';
import ErrorIcon from '../icons/error.svg';
import { pageProgressMessage } from '../stores/page';
import type { TeamDocument } from './CreateTeam/CreateTeamForm';
import type { AllowedRoles } from './CreateTeam/RoleDropdown';
@@ -9,6 +7,8 @@ import type { AllowedMemberStatus } from './TeamDropdown/TeamDropdown';
import { isLoggedIn } from '../lib/jwt';
import { showLoginPopup } from '../lib/popup';
import { getUrlParams } from '../lib/browser';
import { ErrorIcon2 } from './ReactIcons/ErrorIcon2';
import { BuildingIcon } from './ReactIcons/BuildingIcon';
type InvitationResponse = {
team: TeamDocument;
@@ -85,11 +85,7 @@ export function RespondInviteForm() {
if (!invite) {
return (
<div className="container text-center">
<img
alt={'error'}
src={ErrorIcon.src}
className="mx-auto mb-4 mt-24 w-20 opacity-20"
/>
<ErrorIcon2 className="mx-auto mb-4 mt-24 w-20 opacity-20" />
<h2 className={'mb-1 text-2xl font-bold'}>Error</h2>
<p className="mb-4 text-base leading-6 text-gray-600">
@@ -110,11 +106,7 @@ export function RespondInviteForm() {
return (
<div className="container text-center">
<img
alt={'join team'}
src={BuildingIcon.src}
className="mx-auto mb-4 mt-24 w-20 opacity-20"
/>
<BuildingIcon className="mx-auto mb-4 mt-24 w-20 opacity-20" />
<h2 className={'mb-1 text-2xl font-bold'}>Join Team</h2>
<p className="mb-3 text-base leading-6 text-gray-600">

View File

@@ -45,6 +45,8 @@ export function ShareSuccess(props: ShareSuccessProps) {
},
];
const embedHtml = `<iframe src="${baseUrl}/r/embed?id=${roadmapId}" width="100%" height="500px" frameBorder="0"\n></iframe>`;
return (
<div className="flex grow flex-col justify-center">
<div className="mt-5 flex grow flex-col items-center justify-center gap-1.5">
@@ -76,6 +78,23 @@ export function ShareSuccess(props: ShareSuccessProps) {
</p>
)}
<div className="mt-2 border-t pt-2">
<p className="text-sm text-gray-400">
You can also embed this roadmap on your website.
</p>
<div className="mt-2">
<input
onClick={(e) => {
e.currentTarget.select();
copyText(embedHtml);
}}
readOnly={true}
className="w-full resize-none rounded-md border bg-gray-50 p-2 text-sm"
value={embedHtml}
/>
</div>
</div>
{visibility === 'public' && (
<>
<div className="-mx-4 mt-4 flex items-center gap-1.5">

View File

@@ -1,20 +1,25 @@
import { Check, Copy, Facebook, Linkedin, Share2, Twitter } from 'lucide-react';
import { Check, Code2, Copy, Facebook, Linkedin, Share2 } from 'lucide-react';
import { useRef, useState } from 'react';
import { useOutsideClick } from '../hooks/use-outside-click.ts';
import { useCopyText } from '../hooks/use-copy-text.ts';
import { cn } from '../lib/classname.ts';
import { TwitterIcon } from './ReactIcons/TwitterIcon.tsx';
import { EmbedRoadmapModal } from './CustomRoadmap/EmbedRoadmapModal.tsx';
type ShareRoadmapButtonProps = {
roadmapId?: string;
description: string;
pageUrl: string;
allowEmbed?: boolean;
};
export function ShareRoadmapButton(props: ShareRoadmapButtonProps) {
const { description, pageUrl } = props;
const { description, pageUrl, allowEmbed = false, roadmapId } = props;
const { isCopied, copyText } = useCopyText();
const [isEmbedModalOpen, setIsEmbedModalOpen] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
@@ -28,12 +33,21 @@ export function ShareRoadmapButton(props: ShareRoadmapButtonProps) {
setIsDropdownOpen(false);
});
const embedHtml = `<iframe src="https://roadmap.sh/r/embed?id=${roadmapId}" width="100%" height="500px" frameBorder="0"\n></iframe>`;
return (
<div className="relative" ref={containerRef}>
{isEmbedModalOpen && (
<EmbedRoadmapModal
onClose={() => {
setIsEmbedModalOpen(false);
}}
/>
)}
<button
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
className={cn(
'inline-flex items-center justify-center rounded-md bg-yellow-400 px-3 py-1.5 text-xs font-medium hover:bg-yellow-500 sm:text-sm',
'inline-flex h-full items-center justify-center rounded-md bg-yellow-400 px-3 py-1.5 text-xs font-medium hover:bg-yellow-500 sm:text-sm',
{
'bg-yellow-500': isDropdownOpen,
'bg-green-400': isCopied,
@@ -56,7 +70,7 @@ export function ShareRoadmapButton(props: ShareRoadmapButtonProps) {
</button>
{isDropdownOpen && (
<div className="absolute left-0 z-50 mt-1 w-44 rounded-md bg-slate-800 text-sm text-white shadow-lg ring-1 ring-black ring-opacity-5">
<div className="absolute left-0 z-[999] mt-1 w-48 rounded-md bg-slate-800 text-sm text-white shadow-lg ring-1 ring-black ring-opacity-5">
<div className="flex flex-col px-1 py-1">
<button
onClick={() => {
@@ -70,6 +84,20 @@ export function ShareRoadmapButton(props: ShareRoadmapButtonProps) {
</div>
Copy Link
</button>
{allowEmbed && roadmapId && (
<button
onClick={() => {
setIsDropdownOpen(false);
setIsEmbedModalOpen(true);
}}
className="flex w-full items-center gap-2 rounded-sm px-2 py-2 text-sm text-slate-100 hover:bg-slate-700"
>
<div className="flex w-[20px] items-center justify-center">
<Code2 size="15px" className="text-slate-400" />
</div>
Embed Roadmap
</button>
)}
<a
href={twitterUrl}
target={'_blank'}

View File

@@ -1,8 +1,8 @@
import { useState } from 'react';
import type { GroupByRoadmap, TeamMember } from './TeamProgressPage';
import { getUrlParams } from '../../lib/browser';
import ExternalLinkIcon from '../../icons/external-link.svg';
import { useAuth } from '../../hooks/use-auth';
import { LucideExternalLink } from 'lucide-react';
type GroupRoadmapItemProps = {
roadmap: GroupByRoadmap;
@@ -33,11 +33,7 @@ export function GroupRoadmapItem(props: GroupRoadmapItemProps) {
className="group mb-0.5 flex shrink-0 items-center justify-between text-base font-medium leading-none text-black"
target={'_blank'}
>
<img
alt={'link'}
src={ExternalLinkIcon.src}
className="ml-2 h-4 w-4 opacity-20 transition-opacity group-hover:opacity-100"
/>
<LucideExternalLink className="h-4 w-4 opacity-20 transition-opacity group-hover:opacity-100" />
</a>
</div>
</div>
@@ -58,7 +54,7 @@ export function GroupRoadmapItem(props: GroupRoadmapItemProps) {
onClick={() => {
onShowResourceProgress(
member.member,
member.progress?.resourceId!
member.progress?.resourceId!,
);
}}
>

View File

@@ -25,6 +25,7 @@ import type { Node } from 'reactflow';
import { useKeydown } from '../../hooks/use-keydown';
import { useOutsideClick } from '../../hooks/use-outside-click';
import { MemberProgressModalHeader } from './MemberProgressModalHeader';
import { X } from 'lucide-react';
export type ProgressMapProps = {
member: TeamMember;
@@ -284,7 +285,7 @@ export function MemberCustomProgressModal(props: ProgressMapProps) {
}`}
onClick={onClose}
>
<img alt={'close'} src={CloseIcon.src} className="h-4 w-4" />
<X className="h-4 w-4" />
<span className="sr-only">Close modal</span>
</button>
</div>

View File

@@ -12,12 +12,12 @@ import {
type ResourceType,
updateResourceProgress,
} from '../../lib/resource-progress';
import CloseIcon from '../../icons/close.svg';
import { useToast } from '../../hooks/use-toast';
import { useAuth } from '../../hooks/use-auth';
import { pageProgressMessage } from '../../stores/page';
import { MemberProgressModalHeader } from './MemberProgressModalHeader';
import {replaceChildren} from "../../lib/dom.ts";
import { replaceChildren } from '../../lib/dom.ts';
import { XIcon } from 'lucide-react';
export type ProgressMapProps = {
member: TeamMember;
@@ -68,12 +68,12 @@ export function MemberProgressModal(props: ProgressMapProps) {
teamId: string,
memberId: string,
resourceType: string,
resourceId: string
resourceId: string,
) {
const { error, response } = await httpGet<MemberProgressResponse>(
`${
import.meta.env.PUBLIC_API_URL
}/v1-get-member-resource-progress/${teamId}/${memberId}?resourceType=${resourceType}&resourceId=${resourceId}`
}/v1-get-member-resource-progress/${teamId}/${memberId}?resourceType=${resourceType}&resourceId=${resourceId}`,
);
if (error || !response) {
toast.error(error?.message || 'Failed to get member progress');
@@ -160,14 +160,14 @@ export function MemberProgressModal(props: ProgressMapProps) {
resourceType: resourceType as ResourceType,
topicId,
},
newStatus
newStatus,
)
.then(() => {
renderTopicProgress(topicId, newStatus);
getMemberProgress(teamId, member._id, resourceType, resourceId).then(
(data) => {
setMemberProgress(data);
}
},
);
})
.catch((err) => {
@@ -227,7 +227,7 @@ export function MemberProgressModal(props: ProgressMapProps) {
e.preventDefault();
updateTopicStatus(
topicId,
!isCurrentStatusLearning ? 'learning' : 'pending'
!isCurrentStatusLearning ? 'learning' : 'pending',
);
return;
}
@@ -236,7 +236,7 @@ export function MemberProgressModal(props: ProgressMapProps) {
e.preventDefault();
updateTopicStatus(
topicId,
!isCurrentStatusSkipped ? 'skipped' : 'pending'
!isCurrentStatusSkipped ? 'skipped' : 'pending',
);
return;
@@ -298,7 +298,8 @@ export function MemberProgressModal(props: ProgressMapProps) {
}`}
onClick={onClose}
>
<img alt={'close'} src={CloseIcon.src} className="h-4 w-4" />
<XIcon className="h-4 w-4" />
<span className="sr-only">Close modal</span>
</button>
</div>

View File

@@ -4,7 +4,6 @@ import type { TeamDocument } from '../CreateTeam/CreateTeamForm';
import type { TeamResourceConfig } from '../CreateTeam/RoadmapSelector';
import { httpGet, httpPut } from '../../lib/http';
import { pageProgressMessage } from '../../stores/page';
import RoadmapIcon from '../../icons/roadmap.svg';
import type { PageType } from '../CommandMenu/CommandMenu';
import { useStore } from '@nanostores/react';
import { $canManageCurrentTeam } from '../../stores/team';
@@ -28,6 +27,7 @@ import { RoadmapActionDropdown } from './RoadmapActionDropdown';
import { UpdateTeamResourceModal } from '../CreateTeam/UpdateTeamResourceModal';
import { ShareOptionsModal } from '../ShareOptions/ShareOptionsModal';
import { cn } from '../../lib/classname';
import { RoadmapIcon } from '../ReactIcons/RoadmapIcon.tsx';
export function TeamRoadmaps() {
const { t: teamId } = getUrlParams();
@@ -73,7 +73,7 @@ export function TeamRoadmaps() {
async function loadTeam(teamIdToFetch: string) {
const { response, error } = await httpGet<TeamDocument>(
`${import.meta.env.PUBLIC_API_URL}/v1-get-team/${teamIdToFetch}`
`${import.meta.env.PUBLIC_API_URL}/v1-get-team/${teamIdToFetch}`,
);
if (error || !response) {
@@ -87,7 +87,7 @@ export function TeamRoadmaps() {
async function loadTeamResourceConfig(teamId: string) {
const { error, response } = await httpGet<TeamResourceConfig>(
`${import.meta.env.PUBLIC_API_URL}/v1-get-team-resource-config/${teamId}`
`${import.meta.env.PUBLIC_API_URL}/v1-get-team-resource-config/${teamId}`,
);
if (error || !Array.isArray(response)) {
console.error(error);
@@ -127,7 +127,7 @@ export function TeamRoadmaps() {
{
resourceId: roadmapId,
resourceType: 'roadmap',
}
},
);
if (error || !response) {
@@ -156,7 +156,7 @@ export function TeamRoadmaps() {
resourceId: roadmapId,
resourceType: 'roadmap',
removed: [],
}
},
);
if (error || !response) {
@@ -190,13 +190,13 @@ export function TeamRoadmaps() {
}
window.addEventListener(
'custom-roadmap-created',
handleCustomRoadmapCreated
handleCustomRoadmapCreated,
);
return () => {
window.removeEventListener(
'custom-roadmap-created',
handleCustomRoadmapCreated
handleCustomRoadmapCreated,
);
};
}, []);
@@ -252,13 +252,13 @@ export function TeamRoadmaps() {
);
const placeholderRoadmaps = teamResources.filter(
(c: TeamResourceConfig[0]) => c.isCustomResource && !c.topics
(c: TeamResourceConfig[0]) => c.isCustomResource && !c.topics,
);
const customRoadmaps = teamResources.filter(
(c: TeamResourceConfig[0]) => c.isCustomResource && c.topics
(c: TeamResourceConfig[0]) => c.isCustomResource && c.topics,
);
const defaultRoadmaps = teamResources.filter(
(c: TeamResourceConfig[0]) => !c.isCustomResource
(c: TeamResourceConfig[0]) => !c.isCustomResource,
);
const hasRoadmaps =
@@ -272,11 +272,8 @@ export function TeamRoadmaps() {
{addRoadmapModal}
{createRoadmapModal}
<img
alt="roadmap"
src={RoadmapIcon.src}
className="mb-4 h-24 w-24 opacity-10"
/>
<RoadmapIcon className="mb-4 h-24 w-24 opacity-10" />
<h3 className="mb-1 text-2xl font-bold text-gray-900">No roadmaps</h3>
<p className="text-base text-gray-500">
{canManageCurrentTeam
@@ -380,11 +377,11 @@ export function TeamRoadmaps() {
onDelete={() => {
if (
confirm(
'Are you sure you want to remove this roadmap?'
'Are you sure you want to remove this roadmap?',
)
) {
onRemove(resourceConfig.resourceId).finally(
() => {}
() => {},
);
}
}}
@@ -405,7 +402,7 @@ export function TeamRoadmaps() {
)}
</div>
);
}
},
)}
</div>
</div>
@@ -433,7 +430,7 @@ export function TeamRoadmaps() {
'grid grid-cols-1 p-2.5',
canManageCurrentTeam
? 'sm:grid-cols-[auto_172px]'
: 'sm:grid-cols-[auto_110px]'
: 'sm:grid-cols-[auto_110px]',
)}
key={resourceConfig.resourceId}
>
@@ -464,11 +461,11 @@ export function TeamRoadmaps() {
onDelete={() => {
if (
confirm(
'Are you sure you want to remove this roadmap?'
'Are you sure you want to remove this roadmap?',
)
) {
onRemove(resourceConfig.resourceId).finally(
() => {}
() => {},
);
}
}}
@@ -557,11 +554,11 @@ export function TeamRoadmaps() {
onDelete={() => {
if (
confirm(
'Are you sure you want to remove this roadmap?'
'Are you sure you want to remove this roadmap?',
)
) {
onRemove(resourceConfig.resourceId).finally(
() => {}
() => {},
);
}
}}

View File

@@ -15,20 +15,21 @@ import {
} from '../../lib/resource-progress';
import { pageProgressMessage, sponsorHidden } from '../../stores/page';
import { TopicProgressButton } from './TopicProgressButton';
import { ContributionForm } from './ContributionForm';
import { showLoginPopup } from '../../lib/popup';
import { useToast } from '../../hooks/use-toast';
import type {
AllowedLinkTypes,
RoadmapContentDocument,
} from '../CustomRoadmap/CustomRoadmap';
import { markdownToHtml } from '../../lib/markdown';
import { markdownToHtml, sanitizeMarkdown } from '../../lib/markdown';
import { cn } from '../../lib/classname';
import { Ban, FileText, X } from 'lucide-react';
import { getUrlParams } from '../../lib/browser';
import { Spinner } from '../ReactIcons/Spinner';
import { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx';
type TopicDetailProps = {
isEmbed?: boolean;
canSubmitContribution: boolean;
};
@@ -42,9 +43,10 @@ const linkTypes: Record<AllowedLinkTypes, string> = {
};
export function TopicDetail(props: TopicDetailProps) {
const { canSubmitContribution } = props;
const { canSubmitContribution, isEmbed = false } = props;
const [contributionAlertMessage, setContributionAlertMessage] = useState('');
const [hasEnoughLinks, setHasEnoughLinks] = useState(false);
const [contributionUrl, setContributionUrl] = useState('');
const [isActive, setIsActive] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [isContributing, setIsContributing] = useState(false);
@@ -66,12 +68,10 @@ export function TopicDetail(props: TopicDetailProps) {
// Close the topic detail when user clicks outside the topic detail
useOutsideClick(topicRef, () => {
setIsActive(false);
setIsContributing(false);
});
useKeydown('Escape', () => {
setIsActive(false);
setIsContributing(false);
});
// Toggle topic is available even if the component UI is not active
@@ -120,7 +120,6 @@ export function TopicDetail(props: TopicDetailProps) {
setIsActive(true);
sponsorHidden.set(true);
setContributionAlertMessage('');
setTopicId(topicId);
setResourceType(resourceType);
setResourceId(resourceId);
@@ -158,20 +157,27 @@ export function TopicDetail(props: TopicDetailProps) {
}
let topicHtml = '';
if (!isCustomResource) {
// It's full HTML with page body, head etc.
// We only need the inner HTML of the #main-content
const node = new DOMParser().parseFromString(
response as string,
topicHtml = response as string;
const topicDom = new DOMParser().parseFromString(
topicHtml,
'text/html',
);
topicHtml = node?.getElementById('main-content')?.outerHTML || '';
const links = topicDom.querySelectorAll('a');
const urlElem: HTMLElement =
topicDom.querySelector('[data-github-url]')!;
const contributionUrl = urlElem?.dataset?.githubUrl || '';
setContributionUrl(contributionUrl);
setHasEnoughLinks(links.length >= 3);
} else {
setLinks((response as RoadmapContentDocument)?.links || []);
setTopicTitle((response as RoadmapContentDocument)?.title || '');
topicHtml = markdownToHtml(
(response as RoadmapContentDocument)?.description || '',
false,
const sanitizedMarkdown = sanitizeMarkdown(
(response as RoadmapContentDocument).description || '',
);
topicHtml = markdownToHtml(sanitizedMarkdown, false);
}
setIsLoading(false);
@@ -210,34 +216,20 @@ export function TopicDetail(props: TopicDetailProps) {
</div>
)}
{!isLoading && isContributing && (
<ContributionForm
resourceType={resourceType}
resourceId={resourceId}
topicId={topicId}
onClose={(message?: string) => {
if (message) {
setContributionAlertMessage(message);
}
setIsContributing(false);
}}
/>
)}
{!isContributing && !isLoading && !error && (
<>
{/* Actions for the topic */}
<div className="mb-2">
<TopicProgressButton
topicId={topicId}
resourceId={resourceId}
resourceType={resourceType}
onClose={() => {
setIsActive(false);
setIsContributing(false);
}}
/>
{!isEmbed && (
<TopicProgressButton
topicId={topicId}
resourceId={resourceId}
resourceType={resourceType}
onClose={() => {
setIsActive(false);
}}
/>
)}
<button
type="button"
@@ -245,7 +237,6 @@ export function TopicDetail(props: TopicDetailProps) {
className="absolute right-2.5 top-2.5 inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900"
onClick={() => {
setIsActive(false);
setIsContributing(false);
}}
>
<X className="h-5 w-5" />
@@ -298,29 +289,21 @@ export function TopicDetail(props: TopicDetailProps) {
)}
{/* Contribution */}
{canSubmitContribution && (
{canSubmitContribution && !hasEnoughLinks && contributionUrl && (
<div className="mt-8 flex-1 border-t">
<p className="mb-2 mt-2 text-sm leading-relaxed text-gray-400">
Help others learn by submitting links to learn more about this
topic{' '}
Help us improve this introduction and submit a link to a good
article, podcast, video, or any other resource that helped you
understand this topic better.
</p>
<button
onClick={() => {
if (isGuest) {
setIsActive(false);
showLoginPopup();
return;
}
setIsContributing(true);
}}
disabled={!!contributionAlertMessage}
className="block w-full 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"
<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"
>
{contributionAlertMessage
? contributionAlertMessage
: 'Submit a Link'}
</button>
<GitHubIcon className="mr-2 inline-block h-4 w-4 text-white" />
Edit this Content
</a>
</div>
)}
</>

View File

@@ -4,13 +4,13 @@ import { useKeydown } from '../../hooks/use-keydown';
import { httpGet } from '../../lib/http';
import type { ResourceType } from '../../lib/resource-progress';
import { topicSelectorAll } from '../../lib/resource-progress';
import CloseIcon from '../../icons/close.svg';
import { deleteUrlParam, getUrlParams } from '../../lib/browser';
import { useAuth } from '../../hooks/use-auth';
import type { GetRoadmapResponse } from '../CustomRoadmap/CustomRoadmap';
import { ReadonlyEditor } from '../../../editor/readonly-editor';
import { ProgressLoadingError } from './ProgressLoadingError';
import { UserProgressModalHeader } from './UserProgressModalHeader';
import { X } from 'lucide-react';
export type ProgressMapProps = {
userId?: string;
@@ -208,7 +208,7 @@ export function UserCustomProgressModal(props: ProgressMapProps) {
className={`absolute right-2.5 top-3 ml-auto inline-flex items-center rounded-lg bg-gray-100 bg-transparent p-1.5 text-sm text-gray-400 hover:text-gray-900 lg:hidden`}
onClick={onClose}
>
<img alt={'close'} src={CloseIcon.src} className="h-4 w-4" />
<X className="h-4 w-4" />
<span className="sr-only">Close modal</span>
</button>
</div>

View File

@@ -6,11 +6,11 @@ import { useKeydown } from '../../hooks/use-keydown';
import { httpGet } from '../../lib/http';
import type { ResourceType } from '../../lib/resource-progress';
import { topicSelectorAll } from '../../lib/resource-progress';
import CloseIcon from '../../icons/close.svg';
import { deleteUrlParam, getUrlParams } from '../../lib/browser';
import { useAuth } from '../../hooks/use-auth';
import { ProgressLoadingError } from './ProgressLoadingError';
import { UserProgressModalHeader } from './UserProgressModalHeader';
import { X } from 'lucide-react';
export type ProgressMapProps = {
userId?: string;
@@ -70,12 +70,12 @@ export function UserProgressModal(props: ProgressMapProps) {
async function getUserProgress(
userId: string,
resourceType: string,
resourceId: string
resourceId: string,
): Promise<UserProgressResponse | undefined> {
const { error, response } = await httpGet<UserProgressResponse>(
`${
import.meta.env.PUBLIC_API_URL
}/v1-get-user-progress/${userId}?resourceType=${resourceType}&resourceId=${resourceId}`
}/v1-get-user-progress/${userId}?resourceType=${resourceType}&resourceId=${resourceId}`,
);
if (error || !response) {
@@ -86,7 +86,7 @@ export function UserProgressModal(props: ProgressMapProps) {
}
async function getRoadmapSVG(
jsonUrl: string
jsonUrl: string,
): Promise<SVGElement | undefined> {
const { error, response: roadmapJson } = await httpGet(jsonUrl);
if (error || !roadmapJson) {
@@ -216,7 +216,7 @@ export function UserProgressModal(props: ProgressMapProps) {
className={`absolute right-2.5 top-3 ml-auto inline-flex items-center rounded-lg bg-gray-100 bg-transparent p-1.5 text-sm text-gray-400 hover:text-gray-900 lg:hidden`}
onClick={onClose}
>
<img alt={'close'} src={CloseIcon.src} className="h-4 w-4" />
<X className="h-4 w-4" />
<span className="sr-only">Close modal</span>
</button>
</div>

View File

@@ -2,4 +2,4 @@
> Servers are ephemeral, you don't care about them. You only care about the service as a whole.
If a single server dies, it should be of no big concern to you. This is where the real benefit of AWS comes in compared to using physical servers yourself. Normally if a physical server dies, there's panic. With AWS, you don't care, because auto-scaling will give you a fresh new instance soon anyway. Netflix have taken this several steps further with their [simian army](http://techblog.netflix.com/2011/07/netflix-simian-army.html), where they have things like [Chaos Monkey](http://techblog.netflix.com/2012/07/chaos-monkey-released-into-wild.html), which will kill random instances in production (they also have Chaos Gorilla to kill AZs and I've heard rumour of a Chaos Kong to kill regions...). The point is that servers will fail, but this shouldn't matter in your application.
If a single server dies, it should be of no big concern to you. This is where the real benefit of AWS comes in compared to using physical servers yourself. Normally if a physical server dies, there's panic. With AWS, you don't care, because auto-scaling will give you a fresh new instance soon anyway. Netflix have taken this several steps further with their [simian army](http://techblog.netflix.com/2011/07/netflix-simian-army.html), where they have things like [Chaos Monkey](https://github.com/netflix/chaosmonkey), which will kill random instances in production (they also have Chaos Gorilla to kill AZs and I've heard rumour of a Chaos Kong to kill regions...). The point is that servers will fail, but this shouldn't matter in your application.

View File

@@ -37,7 +37,7 @@
- [The Web Performance impact of jQuery](https://twitter.com/TheRealNooshu/status/1509487050122276864)
- [Have Single-Page Apps Ruined the Web? | Transitional Apps](https://www.youtube.com/watch?v=860d8usGC0o)
- [Improve how you architect webapps](https://www.patterns.dev/)
- [Nuxt SSR Optimizing Tips](https://vueschool.io/articles/vuejs-tutorials/nuxt-ssr-optimizing-tips/, Filip Rakowski
- [Nuxt SSR Optimizing Tips](https://vueschool.io/articles/vuejs-tutorials/nuxt-ssr-optimizing-tips/), Filip Rakowski
- [GPU accelerated JavaScript](https://gpu.rocks/#/)
- [Introducing Partytown 🎉: Run Third-Party Scripts From a Web Worker](https://dev.to/adamdbradley/introducing-partytown-run-third-party-scripts-from-a-web-worker-2cnp)
- [Astro: Astro is a fresh but familiar approach to building websites. Astro combines decades of proven performance best practices with the DX improvements of the component-oriented era. Use your favorite JavaScript framework and automatically ship the bare-minimum amount of JavaScript—by default.](https://docs.astro.build/getting-started/)
@@ -71,7 +71,7 @@
- [Idle Until Urgent](https://philipwalton.com/articles/idle-until-urgent/)
- [Browser painting and considerations for web performance](https://css-tricks.com/browser-painting-and-considerations-for-web-performance/)
- [The Cost Of JavaScript In 2018](https://medium.com/@addyosmani/the-cost-of-javascript-in-2018-7d8950fbb5d4) ([Video](https://www.youtube.com/watch?v=i5R7giitymk))
- [Examining Web Worker Performance](https://www.loxodrome.io/post/web-worker-performance/)
- [Examining Web Worker Performance](https://www.jameslmilner.com/posts/web-worker-performance)
- [Front-End Performance Checklist](https://github.com/thedaviddias/Front-End-Performance-Checklist)
- [jankfree](http://jankfree.org/)
- [What forces layout/reflow?](https://gist.github.com/paulirish/5d52fb081b3570c81e3a)

View File

@@ -0,0 +1,394 @@
---
title: 'The 5 Best Backend Development Languages to Master (2024)'
description: 'Discover the best backend development languages to master in 2024.'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
excludedBySlug: '/backend/languages'
seo:
title: 'The 5 Best Backend Development Languages to Master (2024)'
description: 'Discover the best backend development languages to learn right now for career development, with practical tips from an experienced developer.'
isNew: true
type: 'textual'
date: 2024-01-18
sitemap:
priority: 0.7
changefreq: 'weekly'
tags:
- 'guide'
- 'textual-guide'
- 'guide-sitemap'
---
Web development is typically divided into two main categories: [backend development](https://roadmap.sh/backend) and [frontend development](https://roadmap.sh/frontend). Frontend development focuses on the visible part of the application for end-users, i.e. the part that users interact with, while backend development involves writing code that remains unseen but is essential for the functioning of all applications—the business logic.
Two of the key components when it comes to backend development are the programming language that you are going to code in and the database. In this article, we will be looking into a subset of programming languages that could be used for backend development. We will be discussing the pros and cons of each and the community to help you pick the best programming language for backend development.
Without further ado, lets get started!
## What are backend languages?
When it comes to web development, there is a very clear distinction between frontend and backend technologies.
While the frontend ecosystem is quite limited to JavaScript (and other JavaScript-based languages, like TypeScript) due to Browser compatibility, the backend (A.K.A server-side) is a very different scenario.
![Backend Languages](/guides/backend-languages/back-vs-front.png)
Please note that neither of those lists is extensive, as theyre both constantly growing.
You can think of a backend language as one that “runs on the server side”. That said, by that definition, any language is a backend language because even JavaScript nowadays can be used on the backend as well (thanks to Node, Bun, and Deno).
However, we can go one step further and say:
> “A backend language is a server side programming language that has the tools and frameworks required to build web backends”
That will narrow down the list a little bit. But essentially, we can think of backend languages as anything that fits the following list:
- Is able to listen for incoming HTTP/S connections.
- Can access databases.
- Can send HTTP/S requests.
- Can access the filesystem.
- Has a rich ecosystem of tools and frameworks to build web applications.
With those features and a rich ecosystem of libraries and frameworks, a language can definitely be considered “backend-ready”.
## Why learn a backend programming language?
If youre already a backend developer, then the main reason would be to become a more versatile developer. The more languages you know, the better code youll write. Either because youve learned different ways of solving the same problem, or simply because youll be able to contribute to more projects.
If, on the other hand, youre just getting started, the main reason would be that youre entering an industry thats always looking for people.
## Is the market in demand for backend developers?
One thing to keep in mind right now is that the software development market is always in demand for devs. For example, the [U.S. Bureau of Labor Statistics gives our industry a 25% growth rate](https://www.bls.gov/ooh/computer-and-information-technology/software-developers.htm) (demand-wise) from 2022 to 2023, whereas the mean for other industries is 3%.
According to [JetBrains, during 2022, 75% of developers were involved with web development](https://www.jetbrains.com/lp/devecosystem-2022/) in one fashion or another, so whether youre backend devs or frontend devs, there is always someone looking for you.
That said, we also have to consider that this industry is becoming a global industry. While some countries might still be fighting that process back, most developers can directly access the global market and work for any company in the world.
That is a great opportunity for a backend developer who lives in an area where there isnt a big IT industry; however, it also means competing with every other developer in the world. That might cause the illusion that the IT industry is in recession or that there are no job opportunities for developers.
There are always opportunities; its just that you're now after the same job that many others from around the world are after as well.
That said, backend devs are always in high demand because theyre the bread and butter of any web application. Theyre always required to create the underlying platform that will power most systems, so the key to standing out here is to stay up-to-date with the industrys trends and technologies.
Dont get me wrong. You cant possibly be expected to keep up with every single programming language that is released or with all the new frameworks that are created every month. However, keeping an eye on the industry and understanding what survives long enough to become a new industry standard is important. You have to keep updating yourself and learning new technologies/skills constantly; that way, youll stay relevant.
## Is learning a backend language good for your career?
Whether youre a frontend developer looking to become full-stack (someone who can code both the backend and the frontend of an application), or if youre new to the industry and youre thinking if this might be the best place for you, the answer is “yes”.
Backend developers are always in demand, so adding a new tool to your already existing toolbelt (if youre already a dev) will only make you more flexible in the eyes of your employer.
But remember, a language is just a language until you give it context. If youre wondering whether or not one of the backend languages in this article might be for you, the answer will always be “yes”. However, understand that if backend development is new to you, you will also need to pick up other skills and backend technologies around the language, such as:
- Understanding HTTP.
- Learning Structured Query Language (SQL) to query your databases.
- Understanding how APIs work.
- What server side rendering means and how to take advantage of it.
- What web servers are and how to use them/build them.
Otherwise, youll understand the language, but you wont know how to use it for the role of backend development.
## Top 5 Backend Languages to Learn for Web Development
With that introduction out of the way, lets see the top 5 backend programming languages that you might want to learn if youre looking to broaden your horizons in the server-side world.
The languages well cover are:
- Python
- Java
- JavaScript
- PHP
- Go
Why these languages specifically?
Theyre some of the most known and used languages in the industry right now (see [StackOverflows 2023 Developer Survey](https://survey.stackoverflow.co/2023/#most-popular-technologies-language-prof)). That said, keep in mind that these are all great options, and theyre not presented here in any particular order.
### Python
Python has been around for decades already and while its never been the most popular option, it has always managed to stay within the top 5 choices. People love it for being easy to read, straightforward, and able to handle all sorts of tasks, making it a top pick for developers globally. Sure, Python's got a big name in data processing and machine learning, but let's not forget its solid impact on web development!.
What makes Python extra appealing, especially for beginners, is the fact that reading and writing it feels very much like English (or at least, as pseudo code). This makes it a top choice for folks just starting out in coding.
#### Beginner Accessibility and Learning Resources
One of Python's standout features is its beginner-friendly syntax, making it an ideal language for those new to programming. The emphasis on readability and the absence of complex syntax (for the most part), eases the learning curve, enabling new developers to quickly grasp fundamental concepts.
Python's community plays a critical role in its accessibility. Abundant learning resources, tutorials, and documentation are readily available, empowering beginners to progress from basic programming principles to advanced backend development seamlessly. Online platforms like Codecademy, Coursera, realpython.com, and even Google offer comprehensive courses tailored to all skill levels.
#### Practical Applications and Popular Frameworks
Python's versatility is evident in its applicability across a spectrum of industries, from web development and data science to artificial intelligence and automation. In the context of backend development, Python shines brightly with its two standout frameworks: [Django](https://www.djangoproject.com/) and [Flask](https://github.com/pallets/flask).
##### Django
So, let's talk about Django it's like the superhero of web frameworks, at least in the world of Python. This high-level powerhouse is all about that "batteries-included" style, giving you a whole package of tools and features that make development lightning-fast. It follows the [Model-View-Controller](https://www.crio.do/blog/understand-mvc-architecture/) (MVC) architecture that gives your web applications a solid structure, making them scalable and easy to keep up.
Part of that whole “batteries-included” motto means that it comes with an admin panel, an [ORM](https://www.freecodecamp.org/news/what-is-an-orm-the-meaning-of-object-relational-mapping-database-tools/) (Object-Relational Mapping) for smooth data handling, and security features that make sure your project is secured out-of-the-box. All these goodies work together, making Django a top choice for projects, whether they're a walk in the park or a brain-bending challenge.
##### Flask
On the other hand, Flask, a micro-framework, takes a minimalist approach, providing developers with the flexibility to choose components as needed. While Flask may be lighter than Django, it doesn't compromise on functionality. Its simplicity and modularity make it an excellent choice for small to medium-sized projects, allowing developers to tailor the framework to meet specific project requirements.
Both Django and Flask underscore Python's suitability for backend development, offering developers frameworks that cater to diverse project needs while maintaining Python's hallmark readability and efficiency.
#### Pros and Cons of Python
As with all other backend languages in this article, Python has some pros and cons you should consider before picking it as your first backend language.
##### Pros
- The syntax is very easy to learn because its very much like writing English.
- The ecosystem is quite mature and has some nice frameworks that will contain all the tools you need to get started
##### Cons
- Its not the most popular backend language, so while the frameworks available are constantly updated, they arent necessarily using the latest technology trends.
- The GIL (Global Interpreter Lock) limits Pythons performance in multi-threaded applications.
### Java
Java has a massive presence and for good reason (according to [JetBrains survey in 2022, Java was used by 48% of developers](https://w3techs.com/technologies/details/pl-php)).It's the kind of programming language that's everywhere serving up websites, running your favorite apps, and even powering big-scale enterprise systems.
#### Is it worth learning Java?
Now, learning Java, (a strongly typed, object oriented programming language (OOP), is a journey worth taking, but it's not a walk in the park. It's a bit like climbing a mountain you start at the bottom with the basics, and as you ascend, you get into the nitty-gritty of things like object-oriented programming. The process will force you to learn a lot, which is a great thing, by the end youll have a lot of understanding of mechanics and concepts around OOP that can be extrapolated into other languages. However, that can also be overwhelming to some developers who just want to learn by building mini-projects. In those situations, the learning curve of Java might be too long (not steep, but long because there is a lot more to cover than with alternatives such as Python or JavaScript).
That said, the community is big and there are tons of resources, from online courses to forums, helping you navigate the Java landscape. And good reason, considering Java has been around for quite a while.
#### Use Cases and Robust Ecosystem
Java's everywhere. From web development to mobile apps, and even diving into the world of big data, Java's got its fingerprints all over. And if its not the language itself, its the Java Virtual Machine (JVM) powering some other language, like Spark.
Javas the language of choice for many big enterprises given its innate robustness (the first version of the language was released in 1995, its had quite a long time to evolve), and its robust ecosystem of libraries and frameworks makes it a go-to for developers.
#### Pros and Cons of Java
For all its power and robustness, there are some negative (and positive) aspects to picking Java as your first backend language.
##### Pros
- Java has a mature ecosystem with a varied array of libraries and frameworks for you to try. The community has been working on them and evolving them for years in many cases, so theyre quite ready to develop enterprise-ready solutions.
- Javas multithreading support makes it ideal for some processing-heavy tasks in the backend of big applications.
- Javas heavy focus on object oriented programming makes it a great option for developers who enjoy that paradigm.
##### Cons
- Javas verbose syntax might be a problem for some people. While you can still code without an issue, it all comes down to personal preference. If you like to write less and do more with your code, Java might not be the ideal pick for you. Its verbosity can increase development time in some situations.
- Java applications can have higher memory consumption than others, especially compared to others like PHP. While the reason for this is their entire architecture, the fact remains.
### JavaScript (Node.js)
With Node.js in the mix, JavaScript becomes a lingua franca in web development. In other words, you can use the same language both for the frontend (client side) and for the backend (server side) of your application.
That said, keep in mind that depending on the framework youre using, while it might be JavaScript on both sides, the code and logic you use can be considerably different.
Remember that frontend code is often confused with framework code (as in React, Angular, Vue, etc) by some developers, simply because its all JavaScript. But dont be confused, the backend lacks a lot of the extra “juice” added by the browser (like the DOM API and others).
#### Learning Advantages of Node.js
If you've got the basics of JavaScript down, even if your experience has only been on the frontend, diving into Node.js is like leveling up. It lets you use the same language for both frontend and backend, which means less time juggling languages and more time building cool stuff.
The event-driven, non-blocking architecture is one of the main features that make the language so special it makes your web apps fast and efficient without you having to learn more complex concepts such as multi-threading. Plus, the community is constantly growing and there are tutorials everywhere to guide you through the Node.js universe.
If you were to rank languages based on the amount of content out there to learn them, JavaScript would be one of the first ones (if not the first one) on the list.
#### Key Frameworks and Development Tools
Now, let's talk about frameworks. In the case of JavaScript, this topic is so varied that recommending a single option for someone just getting started is really hard.
For example, if you want to go frontend agnostic, or in other words, you dont care about the technology being used to develop the client side of your app, then a good starting option would be [Express.js](https://expressjs.com/). This framework used to be the industry standard. And while thats no longer the case, its still a perfect first choice if youre looking for something with the required functionality to make your life a lot easier.
Now, if on the other hand, youre looking to build the frontend and the backend at the same time, then I would recommend going with [Next.js](https://nextjs.org/) if youre already familiar with React. Or if on the other hand, you prefer Vue.js, then definitely try [Nuxt](https://nuxt.com/). Either one of those will help you get the job done with all the bells and whistles you can think of.
#### Does it make sense to pick up JavaScript as a backend language?
The answer to this question is always going to be “yes”, whether youre coming from the frontend and you already have JS experience or if youre picking it up from scratch. In fact, according to [StackOverflows 2023 survey, JavaScript is the most used language by professionals](https://survey.stackoverflow.co/2023/#most-popular-technologies-language-prof) (with 65.85% of the votes).
![JavaScript Interest](/guides/backend-languages/javascript-interest.png)
If youre coming from the client side, then adopting JS for your backend will let you start working in minutes. Youll probably spend more time learning the backend-specific concepts than the language itself.
On the other hand, if youre coming from zero, or from other programming languages, JS has some quirks, for sure, but if you go the JS route, youre already making way for a potential switch into the frontend in the future. Who knows, maybe in a few months youll also want to start working on the frontend, and by having picked up JS as your main backend language, you have 90% of the work already cut for you.
There is really no downside to picking JS as your first backend language.
#### Pros and Cons of JavaScript
While there might not be a downside to picking JS, there is no perfect language out there, so lets take a look at some of the pros and cons before moving on to the next one.
##### Pros
- Going with JavaScript, youre using the same language on the backend and on the frontend. There is less cognitive load while switching environments if youre the one coding both sides of the app.
- The ecosystem around JavaScript is one of the richest ones you can find. The community is constantly pushing the limits of the language and coming up with new solutions to everyday problems.
- The simple syntax allows you to reduce development time because you dont have to write as much code to achieve good results.
##### Cons
- Asynchronous programming can be hard for some developers coming from other languages, like Python for example.
- The lack of strong types in JavaScript can cause some problems for big codebases.
- The single-thread nature of the language makes it really hard to implement CPU-intensive tasks. While there is support for multi-threading, its not extensive nor commonly used.
- Debugging asynchronous code can be difficult for new developers given the non-linear nature of it.
### PHP
Now, if youre looking for something very well established in the web development industry, just like Java but with a shorter learning curve, then youre probably looking for PHP.
> As a note about PHPs relevancy, while many developers might claim that PHP is a dying tech, according to [W3Techs, over 75% of websites with a backend use PHP](https://w3techs.com/technologies/details/pl-php).
It's the glue that holds a ton of websites together, and its longevity in the web development scene is no accident.
#### Ease of Mastery and Vast Library Support
If you're diving into PHP, you wouldnt be so wrong (no matter what others might tell you). It's got a gentle learning curve, which means you can start building things pretty quickly. Getting everything set up and working will probably take you 10 minutes, and youll be writing your first “hello world” 5 minutes after that.
The vast community support and an ocean of online resources make mastering PHP a breeze. Plus, its library support is like having a toolkit that's always expanding you'll find what you need, whether you're wrangling databases, handling forms, or making your website dance with dynamic content.
If youre looking to pick up PHP, look for the LAMP stack, which stands for **L**inux, **A**pache, **M**ySQL, and **P**HP. With that tech stack, youll have everything you need to start creating websites in no time.
#### Modern PHP Frameworks and Their Impact
If were talking about PHP frameworks, then we gotta talk about [Laravel](https://laravel.com/) and [Symfony](https://symfony.com/). They are like the rockstars of the modern PHP world.
Laravel comes with a lot of tools and features that help you speed up your development process. On the other side, Symfony has a modular architecture, making it a solid choice for projects of all sizes.
These frameworks showcase how PHP has evolved, staying relevant and powerful in the ever-changing landscape of web development.
#### Pros and Cons of PHP
Lets take a look at some of the most common advantages of going with PHP for the backend and some cons to discuss why it might not be the best choice for you.
##### Pros
- PHP is designed for web development, which still makes it a very popular choice for a backend language.
- PHPs community is quite big, considering how old the language is, so if you need help, chances are, someone has the answer youre looking for.
##### Cons
- One of the major complaints developers have about the language is its inconsistent function naming convention. While not a huge problem, it makes it very hard for developers to intuitively find the right function by name. This causes you to constantly verify your code against the documentation to make sure youre not making mistakes.
### Go
Now, let's close in on Go, the programming language born at Google that's all about simplicity and efficiency. Go embraces a clean and straightforward syntax. Despite its simplicity, it focuses heavily on performance, making it an excellent choice for building modern, scalable applications.
According to the [PYPL index](https://pypl.github.io/PYPL.html) (using Google searches to weigh interest of developers in a particular language), we can see a clear worldwide growing interest in Go from the development community:
![Go Interest](/guides/backend-languages/pypl-go-index.png)
#### Concurrency and Scalability
Go stands out in the crowd, especially when it comes to handling concurrency and scalability. Its built-in support for concurrent programming, through goroutines and channels, makes it a standout choice for applications that need to juggle multiple tasks simultaneously. This makes Go particularly adept at handling the demands of today's highly concurrent and distributed systems. In other words, Go is a great choice for building microservices, a type of system that is very commonly used as the backend for complex web applications.
So yes, very relevant.
#### Learning Curve and Developer Productivity
Learning Go is a smooth ride, thanks to its simplicity and extensive documentation. Developers often find themselves quickly transitioning from understanding the basics to building robust applications.
The language's focus on developer productivity is evident in its quick compilation times and the absence of excessive boilerplate code, allowing developers to concentrate on building features rather than wrestling with the language itself.
#### Pros and Cons of Go
Lets take a look at some pros and cons for the last programming language on our list.
##### Pros
- Go code compiles quickly, which in turn leads to very fast development cycles. This is a big plus if youre developing a big application with a large codebase because other options might slow down your process with their compilation times.
- Go's syntax is simple enough to make it easy to learn and understand for new developers.
##### Cons
- Gos ecosystem is quite young when compared to the other alternatives here, so the maturity of the tools available might not be the same as, for example, Java or JavaScript tooling.
### Choosing the Ideal Backend Language
So, are these the best backend programming languages out there? Is there an absolute “best” backend programming language?
As youve probably seen by now, there is no “perfect” or “ideal” backend language. When it comes to picking one out of the huge number of alternatives, you have to consider other aspects outside of the language itself:
- Whats the size of your project? Are you building a large-scale platform? Or just a basic static website?
- Do you mind spending more time learning or do you need to be efficient and start coding right away?
- Do you already have some programming knowledge and would like to pick something that resembles what you already know? Or would you like to pick up something thats entirely different?
- Are you alone? Or are you part of a team?
Once youve answered those questions, youll probably have some idea of where to go, but then you should look into the language itself, specifically into:
- Does it have enough learning resources for you?
- How big and active is the community around it?
- Are the main frameworks still under development? Or have they been parked for a while?
In the end, youre evaluating the language and its ecosystem, making sure theyre both evolving right along the web industry. If you find that there are aspects that are falling behind, then it probably isnt a good choice.
A handy tool when trying to evaluate a language like that is [roadmap.sh](https://roadmap.sh).
[![Roadmap.sh](/guides/backend-languages/backend-roadmap-part.png)](https://roadmap.sh/backend)
<p align="center" style="font-size: 14px; margin-top: -10px; text-align: center">Small section of the full backend roadmap available on <a href="https://roadmap.sh/backend">roadmap.sh</a></p>
There youll find community-maintained roadmaps for many career paths within software development. In particular, for this article, the [backend roadmap](https://roadmap.sh/backend) is a great place to start, because while picking a backend language is important, youll see there that its not just about the language. In fact, there is a lot of tech around the language that is also required (Im referring to databases, git, understanding how client-server communication works, and a big “etc).
### Jumpstarting Your Backend Development Journey
To get started with your backend development journey, it's crucial to have a roadmap that guides you through the learning process and equips you with the skills to build robust and scalable backend systems.
Lucky for you, if youre reading this, that means youve found the most complete and comprehensive roadmap online: [roadmap.sh](https://roadmap.sh), the current [backend roadmap](https://roadmap.sh/backend) is filled with details of everything you should and could (optionally) learn in your journey to becoming a backend developer.
### Guided Learning: From Online Courses to Bootcamps
Online courses and bootcamps serve as invaluable companions on your learning expedition. Platforms like Udemy, Coursera, and freeCodeCamp offer comprehensive backend development courses.
These resources not only cover programming languages like Python, Java, or JavaScript but also dive deep into frameworks like Django, Express.js, or Laravel. For those seeking a more immersive experience, coding bootcamps provide intensive, hands-on training to fast-track your backend development skills.
Whatever choice you go for, make sure youre not following trends or just copying the learning methods of others. Learning is a very personal experience and what works for others might not work for you, and vice versa. So make sure to do the proper research and figure out what option works best for you.
### Building Community Connections for Learning Support
Joining developer communities (there are several on Twitter for example), forums like Stack Overflow, or participating in social media groups dedicated to backend development creates a network of support.
Engaging with experienced developers, sharing challenges, and seeking advice fosters a collaborative learning environment. Attend local meetups or virtual events if you can to connect with professionals in the field, gaining insights and building relationships that can prove invaluable throughout your journey.
### Think about you and your project
There are many ways to go about picking the ideal backend language for you. If there is anything you should take home with you after reading this article, it is that most languages are equivalent in the sense that youll be able to do pretty much everything with any of them.
So what criteria can you use to pick the “right one” for you?
The questions you should also be asking yourself are:
- Whats your preference for a language? Do you like Object Oriented Programming (OOP) or are you more of a functional programming type of dev? Do you like statically typed programming languages or loosely typed ones? Personal preferences should also play an important role at the time of picking your ideal programming language.
- What does my project need? After all, project requirements sometimes dictate technology. Keep that in mind, check if the projects needs and your personal preferences align, and try to weigh in pros and cons if they dont.
In the end, personal preference and actual project requirements (if you have any) are very important, because both will influence how much you enjoy (or dont enjoy) the learning process.
### Crafting a Portfolio to Display Your Backend Skills:
As you accumulate skills and knowledge, showcase your journey through a well-crafted portfolio. Include projects that highlight your backend skills, demonstrating your ability to - design databases, implement server-side logic, and integrate with client side technologies. Whether it's a dynamic web application, a RESTful API, or a data-driven project, your portfolio becomes a tangible representation of your backend development capabilities for potential employers or collaborators.
When it comes to deciding where to publish this portfolio, you have some options, such as directly on your GitHub profile (if you have one), or perhaps on your own personal website where you can share some design thoughts about each project along with the code.
In the end, the important thing is that you should be sharing your experience somewhere, especially when you dont have working experience in the field.
### Conclusion
In the end, there are many backend programming languages to choose from, and what language you go for, is up to you and your particular context/needs. All I can do is guide you to the door, but you have to cross it yourself. Some interesting options are:
- Python with its English-like syntax.
- Java with its formal syntax and enterprise support.
- JavaScript with its flexibility and ability to jump between frontend and backend.
- PHP with its proven record of success.
- And Go, with its performance and scalability focus.
Youre the one who gets to decide, but just know that no matter what you choose, getting started in backend development is a one-way street. Youll be learning from this moment on, and youll be jumping from one language to the other as the field evolves.
Remember that there is a very detailed version of a [backend roadmap here](https://roadmap.sh/backend), it might be a great place to get started! And if youre also interested in frontend development, there is an [equally handy roadmap](https://roadmap.sh/frontend) here as well!

View File

@@ -49,7 +49,7 @@ On a high level, LLMs can be categorized into two types i.e. Base LLMs and Instr
### Base LLMs
Base LLMs are the LLMs which are designed to predict the next word based on the training data. They are not designed to answer questions, carry out conversations or help solve problems. For example, if you give a base LLM the sentence "In this book about LLMs, we will discuss", it might complete this sentence and give you "In this book about LLMs, we will discsus **what LLMs are, how they work, and how you can leverage them in your applications.**." Or if you give it "What are some famous social networks?", instead of answering it might give back "Why do people use social networks?" or "What are some of the benefits of social networks?". As you can see, it is giving us relevant text but it is not answering the question. This is where the Instruction tuned LLMs come in to the picture.
Base LLMs are the LLMs which are designed to predict the next word based on the training data. They are not designed to answer questions, carry out conversations or help solve problems. For example, if you give a base LLM the sentence "In this book about LLMs, we will discuss", it might complete this sentence and give you "In this book about LLMs, we will discuss **what LLMs are, how they work, and how you can leverage them in your applications.**." Or if you give it "What are some famous social networks?", instead of answering it might give back "Why do people use social networks?" or "What are some of the benefits of social networks?". As you can see, it is giving us relevant text but it is not answering the question. This is where the Instruction tuned LLMs come in to the picture.
### Instruction tuned LLMs

View File

@@ -96,7 +96,7 @@ app.listen(3000, () => {
});
```
The important piece to note here is the `express-session` middleware registration which automatically handles the session initialization, cooking parsing and session data retrieval, and so on. In our example here, we are passing the following configuration options:
The important piece to note here is the `express-session` middleware registration which automatically handles the session initialization, cookie parsing and session data retrieval, and so on. In our example here, we are passing the following configuration options:
- `secret`: This is used to sign the session ID cookie. Using a secret that cannot be guessed will reduce the ability to hijack a session.
- `cookie`: Object containing the configuration for session id cookie.
@@ -176,7 +176,7 @@ Next, we have to implement the functionality to process the login form submissio
```javascript
module.exports = function processLogin(req, res) {
if (req.body.username !== 'admin' || req.body.password !== 'admin') {
return res.send('Invalid username or password);
return res.send('Invalid username or password');
}
req.session.userid = req.body.username;

View File

@@ -1,4 +1,4 @@
The Head and Stack in JavaScript Engine are two different data structures that store data in different ways.
The Heap and Stack in JavaScript Engine are two different data structures that store data in different ways.
## Stack

View File

@@ -0,0 +1,17 @@
CommonJS and ES Modules are two different module systems in JavaScript. CommonJS is the module system used in Node.js, while ES Modules are the module system used in browsers and TypeScript.
## CommonJS
```js
const fs = require('fs');
```
CommonJS modules are loaded synchronously. This means that the module is loaded and evaluated before the code using the module is executed. It uses `require()` to load modules and `module.exports` to export modules.
## ES Modules
```js
import fs from 'fs';
```
ES Modules are loaded asynchronously. This means that the module is loaded and evaluated when the module is used. It uses `import` to load modules and `export` to export modules.

View File

@@ -0,0 +1,66 @@
There are four fundamental strategies to report errors in Node.js:
## `try...catch` blocks
`try...catch` blocks are the most basic way to handle errors in JavaScript. They are synchronous and can only be used to handle errors in synchronous code. They are not suitable for asynchronous code, such as callbacks and promises.
```js
import fs from 'node:fs';
try {
const data = fs.readFileSync('file.md', 'utf-8');
console.log(data);
} catch (err) {
console.error(err);
}
```
## Callbacks
Callbacks are the most common way to handle errors in asynchronous code. They are passed as the last argument to a function and are called when the function completes or fails.
```js
import fs from 'node:fs';
fs.readFile('file.md', 'utf-8', (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data);
});
```
## Promises
Promises are a more modern way to handle errors in asynchronous code. They are returned by functions and can be chained together. They are resolved when the function completes and rejected when it fails.
```js
import fs from 'node:fs/promises';
fs.readFile('file.md', 'utf-8')
.then((data) => {
console.log(data);
})
.catch((err) => {
console.error(err);
});
```
## Event emitters
Event emitters are a more advanced way to handle errors in asynchronous code. They are returned by functions and emit an `error` event when they fail. They are resolved when the function completes and rejected when it fails.
```js
import fs from 'node:fs';
const reader = fs.createReadStream('file.md', 'utf-8');
reader.on('data', (data) => {
console.log(data);
});
reader.on('error', (err) => {
console.error(err);
});
```

View File

@@ -0,0 +1,18 @@
The following exit codes are used in Node.js:
- `0`: Success
- `1`: Uncaught Fatal Exception
- `2`: Unused
- `3`: Internal JavaScript Parse Error
- `4`: Internal JavaScript Evaluation Failure
- `5`: Fatal Error
- `6`: Non-function Internal Exception Handler
- `7`: Internal Exception Handler Run-Time Failure
- `8`: Unused
- `9`: Invalid Argument
- `10`: Internal JavaScript Run-Time Failure
- `12`: Invalid Debug Argument
- `13`: Uncaught Exception
- `14`: Unhandled Promise Rejection
- `15`: Fatal Exception
- `16`: Signal Exits

View File

@@ -0,0 +1,18 @@
In order to take user input from the command line, you can use the `readline` module. It provides an interface for reading data from a Readable stream (such as `process.stdin`) one line at a time.
```js
import readline from 'node:readline';
import { stdin as input, stdout as output } from 'node:process';
const rl = readline.createInterface({ input, output });
rl.question('What do you think of Node.js? ', (answer) => {
console.log(`Thank you for your valuable feedback: ${answer}`);
rl.close();
});
rl.on('close', () => {
console.log('\nBYE BYE !!!');
process.exit(0);
});
```

View File

@@ -0,0 +1,25 @@
Order priorities of `process.nextTick`, `Promise`, `setTimeout` and `setImmediate` are as follows:
1. `process.nextTick`: Highest priority, executed immediately after the current event loop cycle, before any other I/O events or timers.
2. `Promise`: Executed in the microtask queue, after the current event loop cycle, but before the next one.
3. `setTimeout`: Executed in the timer queue, after the current event loop cycle, with a minimum delay specified in milliseconds.
4. `setImmediate`: Executed in the check queue, but its order may vary based on the system and load. It generally runs in the next iteration of the event loop after I/O events.
```js
console.log('start');
Promise.resolve().then(() => console.log('Promise'));
setTimeout(() => console.log('setTimeout'), 0);
process.nextTick(() => console.log('process.nextTick'));
setImmediate(() => console.log('setImmediate'));
console.log('end');
// Output:
// start
// end
// process.nextTick
// Promise
// setTimeout
// setImmediate
```
In summary, the order of execution is generally `process.nextTick` > `Promise` > `setTimeout` > `setImmediate`. However, keep in mind that the behavior may vary in specific situations, and the order might be influenced by factors such as system load and other concurrent operations.

View File

@@ -0,0 +1,15 @@
`process.argv` is an array containing the command-line arguments passed when the Node.js process was launched. The first element is the path to the Node.js executable, the second element is the path to the JavaScript file being executed, and the remaining elements are the command-line arguments.
```js
node index.js hello world
```
```js
console.log(process.argv);
// [
// '/usr/local/bin/node', -> path to the Node.js executable
// '/Users/username/projects/nodejs/index.js', -> path to the JavaScript file being executed
// 'hello', -> command-line argument
// 'world' -> command-line argument
// ]
```

View File

@@ -0,0 +1,9 @@
`process.cwd()` returns the current working directory of the Node.js process, while `__dirname` returns the directory name of the current module.
```js
console.log(process.cwd());
// /Users/username/projects/nodejs
console.log(__dirname);
// /Users/username/projects/nodejs/src
```

View File

@@ -0,0 +1,14 @@
To create a minimal `Hello, World!` HTTP server in Node.js, you can use the `http` module. It provides an HTTP server, and the createServer() method sets up a server instance with a callback function to handle incoming requests
```js
import http from 'node:http';
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
});
server.listen(3000, () => {
console.log('Server running at http://localhost:3000/');
});
```

View File

@@ -0,0 +1,227 @@
---
order: 1
briefTitle: 'Node.js'
briefDescription: 'Test, rate and improve your Node.js knowledge with these questions.'
title: 'Node.js Questions'
description: 'Curated list of Node.js questions to test, rate and improve your knowledge. Questions are based on real world experience and knowledge.'
isNew: true
seo:
title: 'Node.js Questions'
description: 'Curated list of Node.js questions to test, rate and improve your knowledge. Questions are based on real world experience and knowledge.'
keywords:
- 'node.js quiz'
- 'node.js questions'
- 'node.js interview questions'
- 'node.js interview'
- 'node.js test'
sitemap:
priority: 1
changefreq: 'monthly'
questions:
- question: What is Node.js?
answer: Node.js is an open-source and cross-platform JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.
topics:
- 'Core'
- 'Beginner'
- question: What is REPL in Node.js?
answer: |
REPL stands for Read-Eval-Print-Loop. It is an interactive shell that allows you to execute JavaScript code and view the output immediately. It is useful for testing small snippets of code and experimenting with the Node.js API.
topics:
- 'Core'
- 'Beginner'
- question: What is the difference between Node.js and JavaScript?
answer: Node.js is a runtime environment for JavaScript. JavaScript is a programming language used to create web applications. Node.js is a runtime environment that can execute JavaScript code outside of a web browser.
topics:
- 'Core'
- 'Beginner'
- question: What is Event Loop in Node.js?
answer: |
The event loop is a single-threaded loop responsible for handling all asynchronous callbacks in Node.js. It continuously checks for events and executes associated callback functions, allowing Node.js to handle asynchronous tasks efficiently. Its non-blocking I/O model ensures that it can process multiple operations simultaneously without waiting for one to complete before moving on to the next, contributing to its scalability and performance.
topics:
- 'Core'
- 'Intermediate'
- question: What is the difference between Node.js and AJAX?
answer: |
Node.js is a server-side runtime for JavaScript, while AJAX is a client-side technique for asynchronous communication with the server.
topics:
- 'Core'
- 'Beginner'
- question: What are modules in Node.js?
answer: |
Modules are reusable blocks of code that can be imported into other files. They are used to encapsulate related code into a single unit of code that can be used in other parts of the program. It allow us to split our code into multiple files and reuse it across multiple files. Some built-in modules include `fs`, `http`, `path`, `url`, `util`, etc.
topics:
- 'Core'
- 'Beginner'
- question: Difference between CommonJS and ESM?
answer: commonjs-vs-esm.md
topics:
- 'Core'
- 'Intermediate'
- question: What is the `global` object in Node.js?
answer: |
The `global` object is a global namespace object that contains all global variables, functions, and objects. It is similar to the `window` object in the browser. It can be accessed from anywhere in the program without importing it.
topics:
- 'Core'
- 'Intermediate'
- question: What is the difference between `process.nextTick()` and `setImmediate()`?
answer: |
`process.nextTick()` and `setImmediate()` are both used to schedule a callback function to be executed in the next iteration of the event loop. The difference is that `process.nextTick()` executes the callback at the end of the current iteration of the event loop, while `setImmediate()` executes the callback at the beginning of the next iteration of the event loop.
topics:
- 'Core'
- 'Intermediate'
- question: What is `setInterval()`?
answer: |
`setInterval()` is a global function that helps you execute a function repeatedly at a fixed delay. It returns an interval ID that uniquely identifies the interval, which can be used to cancel the interval using the `clearInterval()` function.
topics:
- 'Core'
- 'Beginner'
- question: What is `setTimeout()`?
answer: |
`setTimeout()` is a global function that helps you execute a function after a specified delay. It returns a timeout ID that uniquely identifies the timeout, which can be used to cancel the timeout using the `clearTimeout()` function.
topics:
- 'Core'
- 'Beginner'
- question: What are Event Emitters in Node.js?
answer: |
Event Emitters is a class that can be used to emit named events and register listeners for those events. It is used to handle asynchronous events in Node.js.
topics:
- 'Core'
- 'Intermediate'
- question: What is `npm`?
answer: |
`npm` is a package manager for Node.js. It is used to install, update, and remove packages from the Node.js ecosystem. It is also used to manage dependencies for Node.js projects.
topics:
- 'Core'
- 'Beginner'
- question: What is the full form of `npm`?
answer: |
`npm` stands for Node Package Manager.
topics:
- 'Core'
- 'Beginner'
- question: What is `npx`?
answer: |
`npx` is a tool that allows you to run Node.js packages without installing them. It is used to execute Node.js packages that are not installed globally.
topics:
- 'Core'
- 'Beginner'
- question: What is `process.cwd()`?
answer: |
`process.cwd()` returns the current working directory of the Node.js process. It is similar to `pwd` in Unix.
topics:
- 'Core'
- 'Intermediate'
- question: What is the difference between `process.cwd()` and `__dirname`?
answer: process-cwd-vs-dirname.md
topics:
- 'Core'
- 'Intermediate'
- question: What is `__filename`?
answer: |
`__filename` is a global variable that contains the absolute path of the current file.
topics:
- 'Core'
- 'Intermediate'
- question: What is `process.argv`?
answer: process-argv.md
topics:
- 'Core'
- 'Intermediate'
- question: What is the purpose of `fs` module?
answer: |
The File System (fs) module is used to perform file operations such as reading, writing, and deleting files. All file system operations have synchronous and asynchronous forms.
topics:
- 'Core'
- 'Beginner'
- question: What is the purpose of `path` module?
answer: |
The Path module is used to perform operations on file and directory paths. It provides methods for resolving and normalizing paths, joining paths, and extracting file and directory names.
topics:
- 'Core'
- 'Beginner'
- question: How to read a file in Node.js?
answer: |
The `fs.readFile()` method is used to read the contents of a file asynchronously. It takes the path of the file to be read and a callback function as arguments. The callback function is called with two arguments, `err` and `data`. If an error occurs while reading the file, the `err` argument will contain the error object. Otherwise, the `data` argument will contain the contents of the file.
topics:
- 'Core'
- 'Beginner'
- question: How to load environment variables from a `.env` file in Node.js?
answer: |
The `dotenv` package is used to load environment variables from a `.env` file into `process.env`. It is used to store sensitive information such as API keys, database credentials, etc. in a `.env` file instead of hardcoding them in the source code.
topics:
- 'Core'
- 'Beginner'
- question: How to access environment variables in Node.js?
answer: |
Environment variables can be accessed using the `process.env` object. It is an object that contains all the environment variables defined in the current process.
topics:
- 'Core'
- 'Beginner'
- question: How to take user input from the command line in Node.js?
answer: input-from-command-line.md
topics:
- 'Core'
- 'Beginner'
- question: How to create a web server in Node.js?
answer: web-server.md
topics:
- 'Core'
- 'Beginner'
- question: What are streams in Node.js?
answer: |
Streams are objects that allow you to read data from a source or write data to a destination in a continuous manner. They are used to handle large amounts of data efficiently.
topics:
- 'Core'
- 'Intermediate'
- question: What is difference between `fork` and `spawn` methods of `child_process` module?
answer: |
The `fork` method is used when you want to run another JavaScript file in a separate worker. It's like having a friend with a specific task. You can communicate with them via messages and they can send messages back to you. The `spawn` method is used when you want to run a command in a separate process. It's like asking someone to do a specific. You can communicate with them via stdin/stdout/stderr, but it's more like giving orders and getting results.
topics:
- 'Core'
- 'Intermediate'
- question: What is the `os` module?
answer: |
The `os` module provides methods for interacting with the operating system. It can be used to get information about the operating system, such as the hostname, platform, architecture, etc.
topics:
- 'Core'
- 'Beginner'
- question: Can you access the DOM in Node.js?
answer: |
No, you cannot access the DOM in Node.js because it does not have a DOM. It is a server-side runtime for JavaScript, so it does not have access to the browser's DOM.
topics:
- 'Core'
- 'Intermediate'
- question: What is Clustering in Node.js?
answer: |
Clustering is a technique used to distribute the load across multiple processes. It is used to improve the performance and scalability of Node.js applications.
topics:
- 'Core'
- 'Intermediate'
- question: Why memory leak happens in Node.js?
answer: |
Memory leaks happen when a program allocates memory but does not release it when it is no longer needed. This can happen due to bugs in the program or due to the way the program is designed. In Node.js, memory leaks can happen due to the use of closures, circular references, and global variables.
topics:
- 'Core'
- 'Intermediate'
- question: What is the order priority of `process.nextTick`, `Promise`, `setTimeout`, and `setImmediate`?
answer: order-priority.md
topics:
- 'Core'
- 'Intermediate'
- question: What is `process.exit()`?
answer: |
`process.exit()` is a method that can be used to exit the current process. It takes an optional exit code as an argument. If no exit code is specified, it defaults to 0.
topics:
- 'Core'
- 'Intermediate'
- question: Different exit codes in Node.js?
answer: exit-codes.md
topics:
- 'Core'
- 'Intermediate'
- question: How Node.js handle errors?
answer: error-handling.md
topics:
- 'Core'
- 'Intermediate'
---

View File

@@ -3,9 +3,9 @@ jsonUrl: '/jsons/roadmaps/ai-data-scientist.json'
pdfUrl: '/pdfs/roadmaps/ai-data-scientist.pdf'
order: 6
briefTitle: 'AI and Data Scientist'
briefDescription: 'Step by step guide to becoming an AI and Data Scientist in 2023'
briefDescription: 'Step by step guide to becoming an AI and Data Scientist in 2024'
title: 'AI and Data Scientist Roadmap'
description: 'Step by step guide to becoming an AI and Data Scientist in 2023'
description: 'Step by step guide to becoming an AI and Data Scientist in 2024'
hasTopics: true
isNew: true
dimensions:
@@ -21,8 +21,8 @@ seo:
title: 'AI and Data Scientist Roadmap'
description: 'Learn to become an AI and Data Scientist using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern backend development.'
keywords:
- 'ai and data scientist roadmap 2023'
- 'ai and data scientist roadmap 2023'
- 'ai and data scientist roadmap 2024'
- 'ai and data scientist roadmap 2024'
- 'guide to becoming an ai and data scientist'
- 'ai and data scientist roadmap'
- 'ai scientist'

View File

@@ -1,4 +1,5 @@
# MLOps
- [Machine Learning Engineering for Production (MLOps) Specialization](https://imp.i384100.net/nLA5mx)
- [Full Stack Deep Learning](https://fullstackdeeplearning.com/course/2022/)

View File

@@ -2,9 +2,9 @@
pdfUrl: '/pdfs/roadmaps/android.pdf'
order: 4
briefTitle: 'Android'
briefDescription: 'Step by step guide to becoming an Android Developer in 2023'
briefDescription: 'Step by step guide to becoming an Android Developer in 2024'
title: 'Android Developer'
description: 'Step by step guide to becoming an Android developer in 2023'
description: 'Step by step guide to becoming an Android developer in 2024'
hasTopics: true
isNew: true
dimensions:
@@ -12,7 +12,7 @@ dimensions:
height: 2197.76
schema:
headline: 'Android Developer Roadmap'
description: 'Learn how to become a Android Developer with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'
description: 'Learn how to become a Android Developer with this interactive step by step guide in 2024. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'
imageUrl: 'https://roadmap.sh/roadmaps/android.png'
datePublished: '2023-01-24'
dateModified: '2023-10-24'

View File

@@ -1,7 +1,3 @@
# App Shortcuts
Sure, I can provide information about "app shortcuts" feature in Android.
### App Shortcuts
App shortcuts in Android are designed to provide quick and convenient routes to specific actions or functions within your app from the device home screen. To use them, long-press an app's icon and a pop-up menu will appear with the available shortcuts. Depending on the app, you might be able to send a message, make a booking, navigate home, or perform some other specific task without having to first open the app and navigate to the desired function. These shortcuts can also be moved and placed individually on the home screen for even faster access.
App shortcuts in Android are designed to provide quick and convenient routes to specific actions or functions within your app from the device home screen. To use them, long-press an app's icon and a pop-up menu will appear with the available shortcuts. Depending on the app, you might be able to send a message, make a booking, navigate home, or perform some other specific task without having to first open the app and navigate to the desired function. These shortcuts can also be moved and placed individually on the home screen for even faster access.

View File

@@ -3,16 +3,16 @@ jsonUrl: '/jsons/roadmaps/angular.json'
pdfUrl: '/pdfs/roadmaps/angular.pdf'
order: 3
briefTitle: 'Angular'
briefDescription: 'Step by step guide to become a Angular Developer in 2023'
briefDescription: 'Step by step guide to become a Angular Developer in 2024'
title: 'Angular Developer'
description: 'Everything that is there to learn about Angular and the ecosystem in 2023.'
description: 'Everything that is there to learn about Angular and the ecosystem in 2024.'
hasTopics: true
dimensions:
width: 968
height: 2277.8
schema:
headline: 'Angular Developer Roadmap'
description: 'Learn how to become a Angular Developer with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'
description: 'Learn how to become a Angular Developer with this interactive step by step guide in 2024. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'
imageUrl: 'https://roadmap.sh/roadmaps/angular.png'
datePublished: '2023-01-05'
dateModified: '2023-01-20'

View File

@@ -9,4 +9,4 @@ Type guards are typically used for narrowing a type and are pretty similar to fe
Visit the following resources to learn more:
- [Types Guards - Blog](https://blog.logrocket.com/how-to-use-type-guards-typescript/)
- [TypeScript Type Guards Explained](https://www.youtube.com/watch?v=feeeitmtdwg)
- [TypeScript Type Guards Explained](https://www.youtube.com/watch?v=FEeEItMtDwg)

View File

@@ -4,6 +4,5 @@ Marble testing allows you to test asynchronous RxJS code synchronously and step-
Visit the following resources to learn more:
- [Angular Marble Testing: A Brief Introduction](https://www.altamira.ai/blog/angular-marble-testing-a-brief-introduction/)
- [IUnderstanding Marble Diagrams for Reactive Streams](https://medium.com/@jshvarts/read-marble-diagrams-like-a-pro-3d72934d3ef5)
- [Understanding Marble Diagrams for Reactive Streams](https://medium.com/@jshvarts/read-marble-diagrams-like-a-pro-3d72934d3ef5)
- [Interactive Diagrams](https://rxmarbles.com/#from)

View File

@@ -3,9 +3,9 @@ jsonUrl: '/jsons/roadmaps/aspnet-core.json'
pdfUrl: '/pdfs/roadmaps/aspnet-core.pdf'
order: 9
briefTitle: 'ASP.NET Core'
briefDescription: 'Step by step guide to becoming an ASP.NET Core Developer in 2023'
briefDescription: 'Step by step guide to becoming an ASP.NET Core Developer in 2024'
title: 'ASP.NET Core Developer'
description: 'Step by step guide to becoming an ASP.NET core developer in 2023'
description: 'Step by step guide to becoming an ASP.NET core developer in 2024'
isNew: false
hasTopics: true
dimensions:
@@ -13,7 +13,7 @@ dimensions:
height: 2773.45
schema:
headline: 'ASP.NET Core Developer Roadmap'
description: 'Learn how to become a ASP.NET Core Developer with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'
description: 'Learn how to become a ASP.NET Core Developer with this interactive step by step guide in 2024. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'
imageUrl: 'https://roadmap.sh/roadmaps/aspnet-core.png'
datePublished: '2023-01-05'
dateModified: '2023-01-20'

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
---
jsonUrl: '/jsons/roadmaps/aws.json'
pdfUrl: '/pdfs/roadmaps/aws.pdf'
order: 14
briefTitle: 'AWS'
briefDescription: 'Step by step guide to learning AWS in 2024'
title: 'AWS Roadmap'
description: 'Step by step guide to learning AWS in 2024'
isNew: true
hasTopics: true
dimensions:
width: 968
height: 2183.87
schema:
headline: 'AWS Roadmap'
description: 'Learn how to use AWS with this interactive step by step guide in 2024. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'
imageUrl: 'https://roadmap.sh/roadmaps/aws.png'
datePublished: '2023-11-29'
dateModified: '2023-11-29'
seo:
title: 'AWS Roadmap - roadmap.sh'
description: 'Step by step guide to learn AWS in 2024. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'
keywords:
- 'aws tutorial'
- 'step by step guide for aws'
- 'aws for beginners'
- 'how to learn aws'
- 'use aws in production'
- 'aws roadmap 2024'
- 'guide to learning aws'
- 'aws roadmap'
- 'aws learning path'
- 'aws learning roadmap'
- 'container roadmap'
- 'aws'
- 'aws learning guide'
- 'aws skills'
- 'aws for development'
- 'aws for development skills'
- 'aws for development skills test'
- 'aws learning guide'
- 'become a aws expert'
- 'aws career path'
- 'learn aws for development'
- 'what is aws'
- 'aws quiz'
- 'aws interview questions'
relatedRoadmaps:
- 'devops'
- 'backend'
sitemap:
priority: 1
changefreq: 'monthly'
tags:
- 'roadmap'
- 'main-sitemap'
- 'skill-roadmap'
---

View File

@@ -0,0 +1,3 @@
# What is Cloud Computing?
Cloud Computing refers to the delivery of computing services over the internet instead of using local servers. It offers reliable, scalable, and inexpensive cloud computing services which include data storage, databases, applications, analytics, machine learning, and even setting up virtual servers. The biggest names providing cloud computing services are Amazon Web Services (AWS), Microsoft Azure, Google Cloud, and others. The main selling point is that you only pay for the services you use, helping you manage your expenses more effectively.

View File

@@ -0,0 +1,3 @@
# IaaS vs PaaS vs SaaS
"IaaS, PaaS, and SaaS are three types of cloud service models. **IaaS** or Infrastructure as a Service provides users with a resource-based service via virtualization technology, offering computing infrastructure, physical or (more often) virtual machines and other resources. **PaaS** or Platform as a Service provides runtime environments for developing, testing, and managing applications, it is utilized for software development and offers a platform to developers to build applications and services over the internet. **SaaS** or Software as a Service provides on-demand software accessed via the internet, it delivers a complete software solution which you purchase on a pay-as-you-go basis from a cloud service provider."

View File

@@ -0,0 +1,3 @@
# Public vs Private vs Hybrid Cloud
Amazon Web Services (AWS) offers various cloud-based deployment models to cater to varying business needs, including Public, Private, and Hybrid clouds. A **Public Cloud** is a model where the service provider offers resources, such as applications and storage, available to the general public over the internet. Resources may be free, or sold on a pay-per-usage model. On the other hand, a **Private Cloud** is a type of cloud computing that delivers similar advantages to public cloud, including scalability and self-service, but through a proprietary architecture dedicated to a single organization. Unlike public clouds, which deliver services to multiple organizations, a private cloud is dedicated to the needs and goals of a single entity. Lastly, a **Hybrid Cloud** is a solution that combines a private cloud with one or more public cloud services, with proprietary software enabling communication between each distinct service.

View File

@@ -0,0 +1,3 @@
# AWS Global Infrastructure
AWS Global Infrastructure refers to the layout of AWS regions and availability zones around the world. A region is a geographical area, each consisting of two or more availability zones (AZs) which are engineered to be isolated from failures in other AZs. AZs provide inexpensive, low-latency network connectivity to other AZs in the same region. In addition to the regions and AZs, AWS also includes edge locations for content delivery and regional edge caches, enhancing user experience by reducing latency. AWS currently operates in many geographic regions around the world.

View File

@@ -0,0 +1,3 @@
# Shared Responsibility Model
In Amazon Web Services (AWS), the concept of 'Shared Responsibility' pertains to the distribution of security and compliance responsibilities between AWS and the user/client. Under this model, AWS is responsible for the security "of" the cloud — including the infrastructure, hardware, software, networking, and facilities that run AWS cloud services. On the other hand, the user is responsible for security "in" the cloud — this includes managing and configuring the customer-controlled services, protecting account credentials, and securing customer data. This shared model aims to lessen operational burden for users and provide flexible security controls.

View File

@@ -0,0 +1,3 @@
# Well Architected Framework
AWS Well-Architected Framework is a set of strategic guidelines provided by Amazon Web Services. It is designed to provide high-performing and resilient systems while maintaining cost efficiency. The framework divides the architectural best practices across five pillars which include operational excellence, security, reliability, performance efficiency, and cost optimization. With this framework, you can assess and improve your cloud-based architectures and applications by leveraging AWS technologies.

View File

@@ -0,0 +1,9 @@
# Introduction to AWS
AWS (Amazon Web Services) offers a broad set of global cloud-based products including compute, storage, databases, analytics, networking, mobile, developer tools, management tools, IoT, security, and enterprise applications: on-demand, available in seconds, with pay-as-you-go pricing. From data warehousing to deployment tools, directories to content delivery, over 200 AWS services are available. New services can be provisioned quickly, without the upfront fixed expense. This allows enterprises, start-ups, small and medium-sized businesses, and customers in the public sector to access the building blocks they need to respond quickly to changing business requirements. This whitepaper provides you with an overview of the benefits of the AWS Cloud and introduces you to the services that make up the platform.
Learn more from the following links:
- [AWS Documentation](https://docs.aws.amazon.com/)
- [Introduction of AWS](https://docs.aws.amazon.com/whitepapers/latest/aws-overview/introduction.html)
- [AWS Tutorial for Beginners](https://www.youtube.com/watch?v=zA8guDqfv40)

View File

@@ -0,0 +1,9 @@
# Introduction
AWS (Amazon Web Services) offers a broad set of global cloud-based products including compute, storage, databases, analytics, networking, mobile, developer tools, management tools, IoT, security, and enterprise applications: on-demand, available in seconds, with pay-as-you-go pricing. From data warehousing to deployment tools, directories to content delivery, over 200 AWS services are available. New services can be provisioned quickly, without the upfront fixed expense. This allows enterprises, start-ups, small and medium-sized businesses, and customers in the public sector to access the building blocks they need to respond quickly to changing business requirements. This whitepaper provides you with an overview of the benefits of the AWS Cloud and introduces you to the services that make up the platform.
Learn more from the following links:
- [AWS Documentation](https://docs.aws.amazon.com/)
- [Introduction of AWS](https://docs.aws.amazon.com/whitepapers/latest/aws-overview/introduction.html)
- [AWS Tutorial for Beginners](https://www.youtube.com/watch?v=zA8guDqfv40)

View File

@@ -0,0 +1,3 @@
# Instance Types
AWS EC2 instances come in a variety of types optimized to fit different use cases. They are grouped into categories depending on their performance capacity and pricing structure. There are five categories of instance types including General Purpose, Compute Optimized, Memory Optimized, Storage Optimized, and Accelerated Computing instances. Each category is suited best for specific workloads and they consist of different instance types each given a specific name, for example, 't2.micro'. Each instance type has a specific amount of CPU, memory, storage, and network capacity. Understanding the workloads of your applications can help you determine which instance type would be best suited to your needs.

View File

@@ -0,0 +1,3 @@
# CPU Credits
AWS EC2 instances earn CPU Credits when they are idle and consume CPU credits when they are active. A CPU credit provides the performance of a full CPU core for one minute. T2 and T3 instances accrue CPU Credits and use them to burst beyond their baseline performance. For example, a t2.micro instance receives credits continuously at a rate of 6 CPU Credits per hour. The credit balance of an instance can be saved for up to 7 days. When the instance does not have any CPU credits, it performs at the baseline. It's important to note that CPU credit pricing is different and additional to the instance pricing. AWS also offers Unlimited mode for instances that need to burst beyond the baseline performance for extended periods.

View File

@@ -0,0 +1,3 @@
# Storage / Volumes
In AWS, an `Amazon EBS` (Elastic Block Store) is the storage volume used by EC2 (Elastic Compute Cloud) instances. It is designed for data durability, and Amazon EBS volumes automatically replicate within their Availability Zone to prevent data loss due to failure of any individual component. EBS volumes are attached to an EC2 instance, and appear as a network drive that you can mount and format using the file system of your choice. You can use Amazon EBS as the primary storage for data that requires frequent updates, such as a system drive for an instance or storage for a database application.

View File

@@ -0,0 +1,3 @@
# Keypairs
Key pairs are part of Amazon EC2 and are used to securely log into your instances. A key pair consists of a public key and a private key. Amazon EC2 generates the key pair and gives you the private key, whereas the public key is stored with AWS. When you launch an EC2 instance, you specify the name of the key pair. You can then use the private key to securely connect to your instance. Key pairs are region-specific, meaning you need to create separate key pairs for each region in which you operate your instances.

View File

@@ -0,0 +1,3 @@
# Elastic IP
"Elastic IP" in AWS EC2 is a static IPv4 address designed for dynamic cloud computing. An Elastic IP address is associated with your AWS account not a particular instance, and you control that address until you choose to explicitly release it. Unlike traditional static IP addresses, however, Elastic IP addresses allow you to mask the failure of an instance or software by rapidly remapping the address to another instance in your account.

View File

@@ -0,0 +1,3 @@
# User Data Scripts
"User Data Scripts" in EC2 instances are used to perform common automated configuration tasks and even run scripts after the instance starts. These scripts run as the root user, and can be used to install software or download files from an S3 bucket. You can pass up to 16 KB of data to an instance, either as plain text or base64-encoded. The User Data script is executed only one time when the instance is first launched. If you stop and start the instance, the script does not run again. However, it will run on every boot if the instance reboots.

View File

@@ -0,0 +1,3 @@
# Purchasing Options
Amazon EC2 provides several purchasing options to fit different workload needs. The **On-Demand** option allows clients to pay for compute capacity per hour with no long-term commitments. **Reserved Instances** provide a significant discount compared to On-Demand pricing and are ideal for applications required steady state usage. **Spot Instances** allow clients to bid for unused Amazon EC2 capacity and can provide significant savings if flexibility is possible in starting and stopping times. **Dedicated Hosts** are physical EC2 servers dedicated to specific clients, suitable for regulatory requirements and licenses which do not support multi-tenant virtualization, and **Savings Plans** offer reduced rates for committing to a consistent amount of usage for 1 or 3 years.

View File

@@ -0,0 +1,3 @@
# EC2
Amazon Elastic Compute Cloud (EC2) is a web service that provides secure, resizable compute capacity in the cloud. It is designed to make web-scale cloud computing easier for developers. EC2s simple web service interface allows you to obtain and configure capacity with minimal friction. EC2 enables you to scale your compute capacity, develop and deploy applications faster, and run applications on AWS's reliable computing environment. You have the control of your computing resources and can access various configurations of CPU, Memory, Storage, and Networking capacity for your instances.

View File

@@ -0,0 +1,3 @@
# CIDR Blocks
"CIDR" stands for Classless Inter-Domain Routing. In AWS VPC, a CIDR block is the IP address block from which private IPv4 addresses and public IPv4 addresses are allocated when you create a VPC. The CIDR block can range from /28 (16 IP addresses) to /16 (65,536 IP addresses). It represents a network segment and is associated with a network boundary. Upon creation, you cannot change the CIDR block of your VPC, but you can add additional CIDR blocks to it if needed. A VPC's CIDR block should not overlap with any of the existing network's CIDR blocks.

View File

@@ -0,0 +1,3 @@
# Private Subnet
Private subnets in AWS are isolated network segments within your VPC that do not have direct access to the internet. You can use private subnets to run services and applications that should not be directly accessible from the outside world, but still need to communicate with other resources within your VPC. Any instances launched in a private subnet cannot directly send traffic to the internet without routing through a NAT device.

View File

@@ -0,0 +1,3 @@
# Public Subnet
In AWS, a subnet that's designated as `public` is one that has direct access to the Internet. Each subnet that you create runs on its own portion of the AWS network, and you can consider them as logically isolated sections. When a subnet is designated as public, it means an Internet Gateway is attached to it and thus instances within this subnet can easily communicate with the outside net. Each instance that you launch into a public subnet is automatically assigned a private IPv4 address and a public IPv4 address. These addresses don't change and remain with the instance, until it's stopped, terminated or replaced with a different address. This setup allows instances in the public subnet to communicate directly with the internet and other AWS services.

View File

@@ -0,0 +1,3 @@
# Subnets
Subnets or subnetworks in Amazon VPC (Virtual Private Cloud) are divisions of a VPC's IP address range. You can launch Amazon Elastic Compute Cloud (Amazon EC2) instances into a selected subnet. When you create a subnet, you specify the CIDR block for the subnet, which is a subset of the VPC CIDR block. Each subnet must be associated with a route table, which controls the traffic flow between the subnets. There are two types of subnets: public and private. A public subnet is one in which the associated route table directs the subnet to the Internet Gateway (IGW) of the VPC. A private subnet does not have a route to the IGW and hence has no direct route to the internet.

View File

@@ -0,0 +1,3 @@
# Route Tables
A _Route Table_ in AWS VPC is a set of rules, called routes, that are used to determine where network traffic is directed. Each subnet in your VPC must be associated with a route table, which controls the traffic for the subnet. By default, your VPC has a main route table that you can modify. You can also create additional custom route tables for your VPC. A subnet can only be associated with one route table at a time, but you can change the association.

View File

@@ -0,0 +1,3 @@
# Security Groups
Security Groups in AWS act as a virtual firewall for your instance to control inbound and outbound traffic. When you launch an instance in a VPC, you can assign up to five security groups to the instance. Security Groups are stateful — if you send a request from your instance, the response traffic for that request is allowed to flow in regardless of inbound security group rules. You can specify allow rules, but not deny rules. You can specify separate rules for inbound and outbound traffic. Therefore, if you need to allow specific communication between your instances, you'll need to configure both outbound rules for the sender security group and inbound rules for the receiver security group.

View File

@@ -0,0 +1,3 @@
# Internet Gateway
An **Internet Gateway** is a redundant, horizontally scalable component in AWS that performs bi-directional routing between a VPC and the Internet. It serves two purposes; routing outbound traffic from the VPC to the internet (NAT), and routing inbound traffic from the Internet to the VPC. It's automatically highly available and provides bandwidth and redundancy across all AWS Regions. It becomes associated with a VPC upon creation, and cannot be detached or attached to another VPC once created. Security to and from the Internet Gateway can be controlled using route tables and security groups or network ACLs.

View File

@@ -0,0 +1,3 @@
# NAT Gateway
AWS NAT Gateway is a managed service that provides source Network Address Translation (NAT) for instances in a private subnet so they can access the internet securely. It's designed to operate automatically, handling bandwidth scaling, failover, and managing carrier IP addresses. With NAT Gateway, instances within a VPC can access the internet for software updates, patches, etc, but inbound traffic from the internet is prevented, helping maintain the security and privacy of the private subnet. NAT Gateway is redundant within the Availability Zone, providing high availability. It supports TCP, UDP, and ICMP protocols, as well as Port Address Translation (PAT).

View File

@@ -0,0 +1,3 @@
# VPC
Amazon VPC (Virtual Private Cloud) is a service that lets you launch AWS resources in a logically isolated virtual network that you define. It provides advanced security features such as security groups and network access control lists to enable inbound and outbound filtering at the instance and subnet level. Additionally, you can create a Hardware Virtual Private Network (VPN) connection between your corporate datacenter and your VPC to leverage the AWS cloud as an extension of your corporate datacenter.

View File

@@ -0,0 +1,3 @@
# Identity-Based
"Identity-based policies" are one of the types of policies you can create in AWS (Amazon Web Services). They are attached directly to an identity (like an IAM user, group, or role) and control what actions that identity can perform, on which resources, and under what conditions. There are two types - inline and managed. Inline policies are created and managed individually, while managed policies are standalone policies that you can attach to multiple identities. This offers a flexible framework for managing permissions across your AWS resources. These policies are written in a language called JSON (JavaScript Object Notation).

View File

@@ -0,0 +1,3 @@
# Resource-Based
Resource-based policies are attached directly to the AWS resources that receive the permissions. The policy then specifies what actions are allowed or denied on that particular resource. In resource-based policies, you include a `Principal` element in the policy to indicate the IAM users or roles that are granted the permissions. While not all AWS services support resource-based policies, common services that do include Amazon S3 for bucket policies, AWS KMS for key policies, and Amazon SNS for topic policies.

View File

@@ -0,0 +1,3 @@
# Policies
Policies in Amazon IAM (Identity and Access Management) are documents that act as containers for permissions. They are expressed in JSON format in IAM and they define the actions, effects, resources, and optional conditions. There are two types of policies: identity-based policies and resource-based policies. Identity-based policies are attached to an IAM identity, and resource-based policies are attached to a resource. These policies specify what actions are allowed or denied on what resources, under what conditions. They are your primary tool in defining and managing permissions in AWS.

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