Add author page

pull/5258/head
Kamran Ahmed 8 months ago
parent 37ffc2cc62
commit d958a29862
  1. 125
      pnpm-lock.yaml
  2. 42
      src/components/GuideHeader.astro
  3. 24
      src/components/GuideListItem.astro
  4. 11
      src/data/authors/fernando.md
  5. 13
      src/data/authors/kamran.md
  6. 5
      src/data/guides/asymptotic-notation.md
  7. 5
      src/data/guides/avoid-render-blocking-javascript-with-async-defer.md
  8. 38
      src/data/guides/backend-languages.md
  9. 5
      src/data/guides/basic-authentication.md
  10. 5
      src/data/guides/basics-of-authentication.md
  11. 5
      src/data/guides/big-o-notation.md
  12. 5
      src/data/guides/character-encodings.md
  13. 5
      src/data/guides/ci-cd.md
  14. 5
      src/data/guides/consistency-patterns-in-distributed-systems.md
  15. 5
      src/data/guides/design-patterns-for-humans.md
  16. 5
      src/data/guides/dhcp-in-one-picture.md
  17. 5
      src/data/guides/dns-in-one-picture.md
  18. 5
      src/data/guides/free-resources-to-learn-llms.md
  19. 5
      src/data/guides/history-of-javascript.md
  20. 5
      src/data/guides/how-to-setup-a-jump-server.md
  21. 5
      src/data/guides/http-basic-authentication.md
  22. 5
      src/data/guides/http-caching.md
  23. 5
      src/data/guides/introduction-to-llms.md
  24. 5
      src/data/guides/journey-to-http2.md
  25. 5
      src/data/guides/jwt-authentication.md
  26. 5
      src/data/guides/levels-of-seniority.md
  27. 5
      src/data/guides/oauth.md
  28. 5
      src/data/guides/random-numbers.md
  29. 5
      src/data/guides/scaling-databases.md
  30. 5
      src/data/guides/session-authentication.md
  31. 5
      src/data/guides/session-based-authentication.md
  32. 5
      src/data/guides/setup-and-auto-renew-ssl-certificates.md
  33. 5
      src/data/guides/single-command-database-setup.md
  34. 5
      src/data/guides/ssl-tls-https-ssh.md
  35. 5
      src/data/guides/sso.md
  36. 5
      src/data/guides/token-authentication.md
  37. 5
      src/data/guides/unfamiliar-codebase.md
  38. 5
      src/data/guides/what-are-web-vitals.md
  39. 5
      src/data/guides/what-is-internet.md
  40. 5
      src/data/guides/what-is-sli-slo-sla.md
  41. 1
      src/env.d.ts
  42. 2
      src/icons/github.svg
  43. 1
      src/icons/globe.svg
  44. 10
      src/icons/linkedin-2.svg
  45. 73
      src/lib/author.ts
  46. 32
      src/lib/guide.ts
  47. 14
      src/lib/roadmap.ts
  48. 15
      src/lib/video.ts
  49. 110
      src/pages/authors/[authorId].astro

@ -7,7 +7,7 @@ settings:
dependencies:
'@astrojs/react':
specifier: ^3.0.10
version: 3.0.10(@types/react-dom@18.2.19)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)(vite@5.0.12)
version: 3.0.10(@types/react-dom@18.2.19)(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)(vite@5.1.3)
'@astrojs/sitemap':
specifier: ^3.0.5
version: 3.0.5
@ -21,8 +21,8 @@ dependencies:
specifier: ^0.7.1
version: 0.7.1(nanostores@0.9.5)(react@18.2.0)
'@types/react':
specifier: ^18.2.55
version: 18.2.55
specifier: ^18.2.56
version: 18.2.58
'@types/react-dom':
specifier: ^18.2.19
version: 18.2.19
@ -45,8 +45,8 @@ dependencies:
specifier: ^3.0.5
version: 3.0.5
lucide-react:
specifier: ^0.331.0
version: 0.331.0(react@18.2.0)
specifier: ^0.334.0
version: 0.334.0(react@18.2.0)
nanoid:
specifier: ^5.0.5
version: 5.0.5
@ -73,7 +73,7 @@ dependencies:
version: 18.2.0(react@18.2.0)
reactflow:
specifier: ^11.10.4
version: 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)
version: 11.10.4(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)
rehype-external-links:
specifier: ^3.0.0
version: 3.0.0
@ -90,8 +90,8 @@ dependencies:
specifier: ^3.4.1
version: 3.4.1
zustand:
specifier: ^4.5.0
version: 4.5.0(@types/react@18.2.55)(react@18.2.0)
specifier: ^4.5.1
version: 4.5.1(@types/react@18.2.58)(react@18.2.0)
devDependencies:
'@playwright/test':
@ -185,7 +185,7 @@ packages:
prismjs: 1.29.0
dev: false
/@astrojs/react@3.0.10(@types/react-dom@18.2.19)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)(vite@5.0.12):
/@astrojs/react@3.0.10(@types/react-dom@18.2.19)(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)(vite@5.1.3):
resolution: {integrity: sha512-uGRIwKMAn7tva2vxXMyoVIGxWFr0rjZ8ZWIlkTG/vIpnAjD2nM8Cz6B8j7yzj176jvl6gZ6xTbTVPm09aeK0Yw==}
engines: {node: '>=18.14.1'}
peerDependencies:
@ -194,9 +194,9 @@ packages:
react: ^17.0.2 || ^18.0.0
react-dom: ^17.0.2 || ^18.0.0
dependencies:
'@types/react': 18.2.55
'@types/react': 18.2.58
'@types/react-dom': 18.2.19
'@vitejs/plugin-react': 4.2.1(vite@5.0.12)
'@vitejs/plugin-react': 4.2.1(vite@5.1.3)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
ultrahtml: 1.5.2
@ -1102,39 +1102,39 @@ packages:
config-chain: 1.1.13
dev: false
/@reactflow/background@11.3.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0):
/@reactflow/background@11.3.9(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-byj/G9pEC8tN0wT/ptcl/LkEP/BBfa33/SvBkqE4XwyofckqF87lKp573qGlisfnsijwAbpDlf81PuFL41So4Q==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
'@reactflow/core': 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/core': 11.10.4(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)
classcat: 5.0.4
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
zustand: 4.5.0(@types/react@18.2.55)(react@18.2.0)
zustand: 4.5.1(@types/react@18.2.58)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
dev: false
/@reactflow/controls@11.2.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0):
/@reactflow/controls@11.2.9(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-e8nWplbYfOn83KN1BrxTXS17+enLyFnjZPbyDgHSRLtI5ZGPKF/8iRXV+VXb2LFVzlu4Wh3la/pkxtfP/0aguA==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
'@reactflow/core': 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/core': 11.10.4(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)
classcat: 5.0.4
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
zustand: 4.5.0(@types/react@18.2.55)(react@18.2.0)
zustand: 4.5.1(@types/react@18.2.58)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
dev: false
/@reactflow/core@11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0):
/@reactflow/core@11.10.4(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-j3i9b2fsTX/sBbOm+RmNzYEFWbNx4jGWGuGooh2r1jQaE2eV+TLJgiG/VNOp0q5mBl9f6g1IXs3Gm86S9JfcGw==}
peerDependencies:
react: '>=17'
@ -1150,19 +1150,19 @@ packages:
d3-zoom: 3.0.0
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
zustand: 4.5.0(@types/react@18.2.55)(react@18.2.0)
zustand: 4.5.1(@types/react@18.2.58)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
dev: false
/@reactflow/minimap@11.7.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0):
/@reactflow/minimap@11.7.9(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-le95jyTtt3TEtJ1qa7tZ5hyM4S7gaEQkW43cixcMOZLu33VAdc2aCpJg/fXcRrrf7moN2Mbl9WIMNXUKsp5ILA==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
'@reactflow/core': 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/core': 11.10.4(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)
'@types/d3-selection': 3.0.10
'@types/d3-zoom': 3.0.8
classcat: 5.0.4
@ -1170,41 +1170,41 @@ packages:
d3-zoom: 3.0.0
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
zustand: 4.5.0(@types/react@18.2.55)(react@18.2.0)
zustand: 4.5.1(@types/react@18.2.58)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
dev: false
/@reactflow/node-resizer@2.2.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0):
/@reactflow/node-resizer@2.2.9(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-HfickMm0hPDIHt9qH997nLdgLt0kayQyslKE0RS/GZvZ4UMQJlx/NRRyj5y47Qyg0NnC66KYOQWDM9LLzRTnUg==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
'@reactflow/core': 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/core': 11.10.4(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)
classcat: 5.0.4
d3-drag: 3.0.0
d3-selection: 3.0.0
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
zustand: 4.5.0(@types/react@18.2.55)(react@18.2.0)
zustand: 4.5.1(@types/react@18.2.58)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
dev: false
/@reactflow/node-toolbar@1.3.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0):
/@reactflow/node-toolbar@1.3.9(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-VmgxKmToax4sX1biZ9LXA7cj/TBJ+E5cklLGwquCCVVxh+lxpZGTBF3a5FJGVHiUNBBtFsC8ldcSZIK4cAlQww==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
'@reactflow/core': 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/core': 11.10.4(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)
classcat: 5.0.4
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
zustand: 4.5.0(@types/react@18.2.55)(react@18.2.0)
zustand: 4.5.1(@types/react@18.2.58)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
- immer
@ -1700,11 +1700,11 @@ packages:
/@types/react-dom@18.2.19:
resolution: {integrity: sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==}
dependencies:
'@types/react': 18.2.55
'@types/react': 18.2.58
dev: false
/@types/react@18.2.55:
resolution: {integrity: sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA==}
/@types/react@18.2.58:
resolution: {integrity: sha512-TaGvMNhxvG2Q0K0aYxiKfNDS5m5ZsoIBBbtfUorxdH4NGSXIlYvZxLJI+9Dd3KjeB3780bciLyAb7ylO8pLhPw==}
dependencies:
'@types/prop-types': 15.7.11
'@types/scheduler': 0.16.8
@ -1733,7 +1733,7 @@ packages:
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
dev: false
/@vitejs/plugin-react@4.2.1(vite@5.0.12):
/@vitejs/plugin-react@4.2.1(vite@5.1.3):
resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
@ -1744,7 +1744,7 @@ packages:
'@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.7)
'@types/babel__core': 7.20.5
react-refresh: 0.14.0
vite: 5.0.12
vite: 5.1.3
transitivePeerDependencies:
- supports-color
dev: false
@ -3996,8 +3996,8 @@ packages:
engines: {node: '>=12'}
dev: false
/lucide-react@0.331.0(react@18.2.0):
resolution: {integrity: sha512-CHFJ0ve9vaZ7bB2VRAl27SlX1ELh6pfNC0jS96qGpPEEzLkLDGq4pDBFU8RhOoRMqsjXqTzLm9U6bZ1OcIHq7Q==}
/lucide-react@0.334.0(react@18.2.0):
resolution: {integrity: sha512-y0Rv/Xx6qAq4FutZ3L/efl3O9vl6NC/1p0YOg6mBfRbQ4k1JCE2rz0rnV7WC8Moxq1RY99vLATvjcqUegGJTvA==}
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0
dependencies:
@ -5543,18 +5543,18 @@ packages:
loose-envify: 1.4.0
dev: false
/reactflow@11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0):
/reactflow@11.10.4(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-0CApYhtYicXEDg/x2kvUHiUk26Qur8lAtTtiSlptNKuyEuGti6P1y5cS32YGaUoDMoCqkm/m+jcKkfMOvSCVRA==}
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
'@reactflow/background': 11.3.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/controls': 11.2.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/core': 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/minimap': 11.7.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/node-resizer': 2.2.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/node-toolbar': 1.3.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/background': 11.3.9(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/controls': 11.2.9(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/core': 11.10.4(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/minimap': 11.7.9(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/node-resizer': 2.2.9(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/node-toolbar': 1.3.9(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
transitivePeerDependencies:
@ -6745,41 +6745,6 @@ packages:
vfile-message: 4.0.2
dev: false
/vite@5.0.12:
resolution: {integrity: sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
'@types/node': ^18.0.0 || >=20.0.0
less: '*'
lightningcss: ^1.21.0
sass: '*'
stylus: '*'
sugarss: '*'
terser: ^5.4.0
peerDependenciesMeta:
'@types/node':
optional: true
less:
optional: true
lightningcss:
optional: true
sass:
optional: true
stylus:
optional: true
sugarss:
optional: true
terser:
optional: true
dependencies:
esbuild: 0.19.11
postcss: 8.4.33
rollup: 4.9.6
optionalDependencies:
fsevents: 2.3.3
dev: false
/vite@5.1.3:
resolution: {integrity: sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==}
engines: {node: ^18.0.0 || >=20.0.0}
@ -6964,8 +6929,8 @@ packages:
resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
dev: false
/zustand@4.5.0(@types/react@18.2.55)(react@18.2.0):
resolution: {integrity: sha512-zlVFqS5TQ21nwijjhJlx4f9iGrXSL0o/+Dpy4txAP22miJ8Ti6c1Ol1RLNN98BMib83lmDH/2KmLwaNXpjrO1A==}
/zustand@4.5.1(@types/react@18.2.58)(react@18.2.0):
resolution: {integrity: sha512-XlauQmH64xXSC1qGYNv00ODaQ3B+tNPoy22jv2diYiP4eoDKr9LA+Bh5Bc3gplTrFdb6JVI+N4kc1DZ/tbtfPg==}
engines: {node: '>=12.7.0'}
peerDependencies:
'@types/react': '>=16.8'
@ -6979,7 +6944,7 @@ packages:
react:
optional: true
dependencies:
'@types/react': 18.2.55
'@types/react': 18.2.58
react: 18.2.0
use-sync-external-store: 1.2.0(react@18.2.0)
dev: false

@ -6,28 +6,32 @@ export interface Props {
}
const { guide } = Astro.props;
const { frontmatter } = guide;
const { author } = frontmatter;
const { frontmatter, author } = guide;
---
<div class='bg-white border-b py-5 sm:py-12'>
<div class='border-b bg-white py-5 sm:py-12'>
<div class='container text-left sm:text-center'>
<p
class='text-gray-400 hidden sm:flex items-center justify-start sm:justify-center'
class='hidden items-center justify-start text-gray-400 sm:flex sm:justify-center'
>
<a
href={author.url}
target='_blank'
class='font-medium hover:text-gray-600 inline-flex items-center hover:underline'
>
<img
alt={author.name}
src={author.imageUrl}
class='w-5 h-5 inline mr-2 rounded-full'
/>
{author.name}
</a>
<span class='mx-1.5'>&middot;</span>
{
author?.frontmatter && (
<>
<a
href={`/authors/${author.id}`}
class='inline-flex items-center font-medium hover:text-gray-600 hover:underline'
>
<img
alt={author.frontmatter.name}
src={author.frontmatter.imageUrl}
class='mr-2 inline h-5 w-5 rounded-full'
/>
{author.frontmatter.name}
</a>
<span class='mx-1.5'>&middot;</span>
</>
)
}
<span class='capitalize'>{frontmatter.type} Guide</span>
<span class='mx-1.5'>&middot;</span>
<a
@ -36,10 +40,10 @@ const { author } = frontmatter;
target='_blank'>Improve this Guide</a
>
</p>
<h1 class='text-2xl sm:text-5xl my-0 sm:my-3.5 font-bold'>
<h1 class='my-0 text-2xl font-bold sm:my-3.5 sm:text-5xl'>
{frontmatter.title}
</h1>
<p class='hidden sm:block text-gray-400 text-xl'>
<p class='hidden text-xl text-gray-400 sm:block'>
{frontmatter.description}
</p>
</div>

@ -1,5 +1,5 @@
---
import type { GuideFileType } from "../lib/guide";
import type { GuideFileType } from '../lib/guide';
export interface Props {
guide: GuideFileType;
@ -11,30 +11,34 @@ const { frontmatter, id } = guide;
<a
class:list={[
"block no-underline py-2 group text-md items-center text-gray-600 hover:text-blue-600 flex justify-between border-b",
'text-md group block flex items-center justify-between border-b py-2 text-gray-600 no-underline hover:text-blue-600',
]}
href={frontmatter.excludedBySlug ? frontmatter.excludedBySlug : `/guides/${id}`}
href={frontmatter.excludedBySlug
? frontmatter.excludedBySlug
: `/guides/${id}`}
>
<span class="group-hover:translate-x-2 transition-transform">
<span
class='text-sm transition-transform group-hover:translate-x-2 md:text-base'
>
{frontmatter.title}
{
frontmatter.isNew && (
<span class="bg-green-300 text-green-900 text-xs font-medium px-1.5 py-0.5 rounded-sm uppercase ml-1.5">
<span class='ml-1.5 rounded-sm bg-green-300 px-1.5 py-0.5 text-xs font-medium uppercase text-green-900'>
New
<span class="hidden sm:inline">
<span class='hidden sm:inline'>
&middot;
{new Date(frontmatter.date).toLocaleString("default", {
month: "long",
{new Date(frontmatter.date).toLocaleString('default', {
month: 'long',
})}
</span>
</span>
)
}
</span>
<span class="capitalize text-gray-500 text-xs hidden sm:block">
<span class='hidden text-xs capitalize text-gray-500 sm:block'>
{frontmatter.type}
</span>
<span class="text-gray-400 text-xs block sm:hidden"> &raquo;</span>
<span class='block text-xs text-gray-400 sm:hidden'> &raquo;</span>
</a>

@ -0,0 +1,11 @@
---
name: 'Fernando Doglio'
imageUrl: '/authors/fernando.jpeg'
social:
twitter: 'https://twitter.com/deleteman123'
linkedin: 'https://www.linkedin.com/in/fernandodoglio'
---
With two decades of experience in Software Development, Fernando Doglio excels in diverse languages like Ruby, Perl, PHP, Python, and JavaScript. He's led teams in crafting scalable architectures for both in-house and cloud infrastructures.
An author of 8 technical books and over 250 articles, Fernando's current role as a Dev Advocate allows him to blend his passion for coding with content creation, enhancing developer experiences with products through engaging outreach.

@ -0,0 +1,13 @@
---
name: 'Kamran Ahmed'
imageUrl: '/authors/kamran.jpeg'
social:
linkedin: 'https://www.linkedin.com/in/kamrify'
twitter: 'https://twitter.com/kamrify'
github: 'https://github.com/kamranahmedse'
website: 'https://kamranahmed.info'
---
Kamran is the founder of **roadmap.sh**. He has a decade long experience working mostly with startups and scale-ups. Over the years, he has worked with a variety of technologies in a variety of domains and have worn several different hats. He is working full time on roadmap.sh at the moment.
He is also a Google Developer Expert and a GitHub Star. He is a huge proponent of open-source, and has authored several popular open-source projects. He is [the second most starred developer](https://twitter.com/kamrify/status/1750345095587754382) on GitHub globally.

@ -1,10 +1,7 @@
---
title: 'Asymptotic Notation'
description: 'Learn the basics of measuring the time and space complexity of algorithms'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Asymptotic Notation - roadmap.sh'
description: 'Learn the basics of measuring the time and space complexity of algorithms'

@ -1,10 +1,7 @@
---
title: 'Async and Defer Script Loading'
description: 'Learn how to avoid render blocking JavaScript using async and defer scripts.'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Async and Defer Script Loading - roadmap.sh'
description: 'Learn how to avoid render blocking JavaScript using async and defer scripts.'

@ -1,10 +1,7 @@
---
title: 'The 5 Best Backend Development Languages to Master (2024)'
description: 'Discover the best backend development languages to master in 2024.'
author:
name: 'Fernando Doglio'
url: 'https://twitter.com/deleteman123'
imageUrl: '/authors/fernando.jpeg'
authorId: fernando
excludedBySlug: '/backend/languages'
seo:
title: 'The 5 Best Backend Development Languages to Master (2024)'
@ -116,9 +113,9 @@ What makes Python extra appealing, especially for beginners, is the fact that re
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.
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
#### 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).
@ -154,7 +151,7 @@ Java has a massive presence and for good reason (according to [JetBrain’s surv
#### 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 you’ll 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).
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 you’ll 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.
@ -197,7 +194,7 @@ If you were to rank languages based on the amount of content out there to learn
#### 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.
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 don’t 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 that’s no longer the case, it’s still a perfect first choice if you’re looking for something with the required functionality to make your life a lot easier.
@ -205,7 +202,7 @@ Now, if on the other hand, you’re looking to build the frontend and the backen
#### Does it make sense to pick up JavaScript as a backend language?
The answer to this question is always going to be “yes”, whether you’re coming from the frontend and you already have JS experience or if you’re picking it up from scratch. In fact, according to [StackOverflow’s 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).
The answer to this question is always going to be “yes”, whether you’re coming from the frontend and you already have JS experience or if you’re picking it up from scratch. In fact, according to [StackOverflow’s 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)
@ -234,7 +231,7 @@ While there might not be a downside to picking JS, there is no perfect language
### PHP
Now, if you’re looking for something very well established in the web development industry, just like Java but with a shorter learning curve, then you’re probably looking for PHP.
Now, if you’re looking for something very well established in the web development industry, just like Java but with a shorter learning curve, then you’re probably looking for PHP.
> As a note about PHP’s 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).
@ -242,7 +239,7 @@ It's the glue that holds a ton of websites together, and its longevity in the we
#### Ease of Mastery and Vast Library Support
If you're diving into PHP, you wouldn’t 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 you’ll be writing your first “hello world” 5 minutes after that.
If you're diving into PHP, you wouldn’t 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 you’ll 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.
@ -250,9 +247,9 @@ If you’re looking to pick up PHP, look for the LAMP stack, which stands for **
#### Modern PHP Frameworks and Their Impact
If we’re 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.
If we’re 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.
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.
@ -337,7 +334,7 @@ Lucky for you, if you’re reading this, that means you’ve found the most comp
### 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.
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.
@ -345,7 +342,7 @@ Whatever choice you go for, make sure you’re not following trends or just copy
### 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.
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.
@ -368,7 +365,7 @@ As you accumulate skills and knowledge, showcase your journey through a well-cra
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 don’t have working experience in the field.
In the end, the important thing is that you should be sharing your experience somewhere, especially when you don’t have working experience in the field.
### Conclusion
@ -383,12 +380,3 @@ In the end, there are many backend programming languages to choose from, and wha
You’re 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. You’ll be learning from this moment on, and you’ll 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 you’re also interested in frontend development, there is an [equally handy roadmap](https://roadmap.sh/frontend) here as well!

@ -1,10 +1,7 @@
---
title: 'Basic Authentication'
description: 'Understand what is basic authentication and how it is implemented'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Basic Authentication - roadmap.sh'
description: 'Understand what is basic authentication and how it is implemented'

@ -1,10 +1,7 @@
---
title: 'Basics of Authentication'
description: 'Learn the basics of Authentication and Authorization'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Basics of Authentication - roadmap.sh'
description: 'Learn the basics of Authentication and Authorization'

@ -1,10 +1,7 @@
---
title: 'Big-O Notation'
description: 'Easy to understand explanation of Big-O notation without any fancy terms'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Big-O Notation - roadmap.sh'
description: 'Easy to understand explanation of Big-O notation without any fancy terms'

@ -1,10 +1,7 @@
---
title: 'Character Encodings'
description: 'Covers the basics of character encodings and explains ASCII vs Unicode'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Character Encodings - roadmap.sh'
description: 'Covers the basics of character encodings and explains ASCII vs Unicode'

@ -1,10 +1,7 @@
---
title: 'What is CI and CD?'
description: 'Learn the basics of CI/CD and how to implement that with GitHub Actions.'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'What is CI and CD? - roadmap.sh'
description: 'Learn the basics of CI/CD and how to implement that with GitHub Actions.'

@ -1,10 +1,7 @@
---
title: 'Consistency Patterns'
description: 'Everything you need to know about Week, Strong and Eventual Consistency'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Consistency Patterns - roadmap.sh'
description: 'Everything you need to know about Week, Strong and Eventual Consistency'

@ -1,10 +1,7 @@
---
title: 'Design Patterns for Humans'
description: 'A language agnostic, ultra-simplified explanation to design patterns'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Design Patterns for Humans - roadmap.sh'
description: 'A language agnostic, ultra-simplified explanation to design patterns'

@ -1,10 +1,7 @@
---
title: 'DHCP in One Picture'
description: 'Here is what happens when a new device joins the network.'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'DHCP in One Picture - roadmap.sh'
description: 'Here is what happens when a new device joins the network.'

@ -1,10 +1,7 @@
---
title: 'DNS in One Picture'
description: 'Quick illustrative guide on how a website is found on the internet.'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'DNS in One Picture - roadmap.sh'
description: 'Quick illustrative guide on how a website is found on the internet.'

@ -1,10 +1,7 @@
---
title: '5 Free Resources to Master LLMs'
description: 'Dive into the world of LLMs with these free resources'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: '5 Free Resources to Master Language Models (LLMs) - roadmap.sh'
description: 'Looking to dive into the fascinating world of Language Models (LLMs)? Discover the top 5 free resources that will help you learn and excel in understanding LLMs. From comprehensive tutorials to interactive courses, this blog post provides you with the ultimate guide to sharpen your skills and unravel the potential of language models. Start your journey today and become a pro in LLMs without spending a dime!'

@ -1,10 +1,7 @@
---
title: 'Brief History of JavaScript'
description: 'How JavaScript was introduced and evolved over the years'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Brief History of JavaScript - roadmap.sh'
description: 'How JavaScript was introduced and evolved over the years'

@ -1,10 +1,7 @@
---
title: 'Jump Servers: What, Why and How'
description: 'Learn what is a Jump Server and how to set it up for SSH access.'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Jump Servers: What, Why and How - roadmap.sh'
description: 'Learn what is a Jump Server and how to set it up for SSH access.'

@ -1,10 +1,7 @@
---
title: 'HTTP Basic Authentication'
description: 'Learn what is HTTP Basic Authentication and how to implement it in Node.js'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'HTTP Basic Authentication - roadmap.sh'
description: 'Learn what is HTTP Basic Authentication and how to implement it in Node.js'

@ -1,10 +1,7 @@
---
title: 'HTTP Caching'
description: 'Everything you need to know about web caching'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'HTTP Caching - roadmap.sh'
description: 'Everything you need to know about web caching'

@ -1,10 +1,7 @@
---
title: 'Introduction to LLMs'
description: 'What are LLMs, how does ChatGPT and other LLMs work?'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Introduction to LLMs - roadmap.sh'
description: 'What are LLMs, how does ChatGPT and other LLMs work?'

@ -1,10 +1,7 @@
---
title: 'Journey to HTTP/2'
description: 'The evolution of HTTP. How it all started and where we stand today'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Journey to HTTP/2 - roadmap.sh'
description: 'The evolution of HTTP. How it all started and where we stand today'

@ -1,10 +1,7 @@
---
title: 'JWT Authentication'
description: 'Understand what is JWT authentication and how is it implemented'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'JWT Authentication - roadmap.sh'
description: 'Understand what is JWT authentication and how is it implemented'

@ -1,10 +1,7 @@
---
title: 'Levels of Seniority'
description: 'How to Step Up as a Junior, Mid Level or a Senior Developer?'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Levels of Seniority - roadmap.sh'
description: 'How to Step Up as a Junior, Mid Level or a Senior Developer?'

@ -1,10 +1,7 @@
---
title: 'OAuth — Open Authorization'
description: 'Learn and understand what is OAuth and how it works'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'OAuth — Open Authorization - roadmap.sh'
description: 'Learn and understand what is OAuth and how it works'

@ -1,10 +1,7 @@
---
title: 'Random Numbers: Are they?'
description: 'Learn how they are generated and why they may not be truly random.'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Random Numbers: Are they? - roadmap.sh'
description: 'Learn how they are generated and why they may not be truly random.'

@ -1,10 +1,7 @@
---
title: 'Scaling Databases'
description: 'Learn the ups and downs of different database scaling strategies'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Scaling Databases - roadmap.sh'
description: 'Learn the ups and downs of different database scaling strategies'

@ -1,10 +1,7 @@
---
title: 'Session Based Authentication'
description: 'Understand what is session based authentication and how it is implemented'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Session Based Authentication - roadmap.sh'
description: 'Understand what is session based authentication and how it is implemented'

@ -1,10 +1,7 @@
---
title: 'Session Based Authentication'
description: 'Learn what is Session Based Authentication and how to implement it in Node.js'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Session Based Authentication - roadmap.sh'
description: 'Learn what is Session Based Authentication and how to implement it in Node.js'

@ -1,10 +1,7 @@
---
title: "Guide to Let's Encrypt SSL Setup"
description: "Learn how to protect your website using Let's Encrypt SSL Certificates."
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: "Guide to Let's Encrypt SSL Setup - roadmap.sh"
description: "Learn how to protect your website using Let's Encrypt SSL Certificates."

@ -1,10 +1,7 @@
---
title: 'Single Command Database Setup'
description: 'Learn how to run MySQL, PostgreSQL, or MongoDB in Docker with single Command'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Single Command Database Setup - roadmap.sh'
description: 'Learn how to run MySQL, PostgreSQL, or MongoDB in Docker with single Command'

@ -1,10 +1,7 @@
---
title: 'SSL vs TLS vs SSH'
description: 'Quick tidbit on the differences between SSL, TLS, HTTPS and SSH'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'SSL vs TLS vs SSH - roadmap.sh'
description: 'Quick tidbit on the differences between SSL, TLS, HTTPS and SSH'

@ -1,10 +1,7 @@
---
title: 'SSO — Single Sign On'
description: 'Learn the basics of SAML and understand how does Single Sign On work.'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'SSO — Single Sign On - roadmap.sh'
description: 'Learn the basics of SAML and understand how does Single Sign On work.'

@ -1,10 +1,7 @@
---
title: 'Token Based Authentication'
description: 'Understand what is token based authentication and how it is implemented'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Token Based Authentication - roadmap.sh'
description: 'Understand what is token based authentication and how it is implemented'

@ -1,10 +1,7 @@
---
title: 'Unfamiliar Codebase'
description: 'Tips on getting familiar with an unfamiliar codebase'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'Unfamiliar Codebase - roadmap.sh'
description: 'Tips on getting familiar with an unfamiliar codebase'

@ -1,10 +1,7 @@
---
title: 'What are Web Vitals?'
description: 'Learn what are the core web vitals and how to measure them.'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'What are Web Vitals? - roadmap.sh'
description: 'Learn what are the core web vitals and how to measure them.'

@ -1,10 +1,7 @@
---
title: 'How does the internet work?'
description: 'Learn the basics of internet and everything involved with this short video series'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'How does the internet work? - roadmap.sh'
description: 'Learn the basics of internet and everything involved with this short video series'

@ -1,10 +1,7 @@
---
title: 'SLIs, SLOs and SLAs'
description: 'Learn what are different indicators for performance identification of any service.'
author:
name: 'Kamran Ahmed'
url: 'https://twitter.com/kamrify'
imageUrl: '/authors/kamranahmedse.jpeg'
authorId: 'kamran'
seo:
title: 'SLIs, SLOs and SLAs - roadmap.sh'
description: 'Learn what are different indicators for performance identification of any service.'

1
src/env.d.ts vendored

@ -1,4 +1,3 @@
/// <reference types="astro/client" />
import 'astro/client';
interface ImportMetaEnv {

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98 96" xmlns:v="https://vecta.io/nano"><path fill-rule="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"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98 96" xmlns:v="https://vecta.io/nano"><path fill-rule="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="currentColor"/></svg>

Before

Width:  |  Height:  |  Size: 941 B

After

Width:  |  Height:  |  Size: 946 B

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm9.567 9.098c-.059-.058-.127-.108-.206-.138-.258-.101-1.35.603-1.515.256-.108-.231-.327.148-.578.008-.121-.067-.459-.52-.611-.465-.312.112.479.974.694 1.087.203-.154.86-.469 1.002-.039.271.812-.745 1.702-1.264 2.171-.775.702-.63-.454-1.159-.86-.277-.213-.274-.667-.555-.824-.125-.071-.7-.732-.694-.821l-.017.167c-.095.072-.297-.27-.319-.325 0 .298.485.772.646 1.011.273.409.42 1.005.756 1.339.179.18.866.923 1.045.908l.921-.437c.649.154-1.531 3.237-1.738 3.619-.171.321.139 1.112.114 1.49-.029.437-.374.579-.7.817-.35.255-.268.752-.562.934-.521.321-.897 1.366-1.639 1.361-.219-.001-1.151.364-1.273.007-.095-.258-.223-.455-.356-.71-.131-.25-.015-.51-.175-.731-.11-.154-.479-.502-.513-.684-.002-.157.118-.632.283-.715.231-.118.044-.462.016-.663-.048-.357-.27-.652-.535-.859-.393-.302-.189-.542-.098-.974 0-.206-.126-.476-.402-.396-.57.166-.396-.445-.812-.417-.299.021-.543.211-.821.295-.349.104-.707-.083-1.053-.126-1.421-.179-1.885-1.804-1.514-2.976.037-.192-.115-.547-.048-.696.159-.352.485-.752.768-1.021.16-.152.365-.113.553-.231.29-.182.294-.558.578-.789.404-.328.956-.321 1.482-.392.281-.037 1.35-.268 1.518-.06 0 .039.193.611-.019.578.438.023 1.061.756 1.476.585.213-.089.135-.744.573-.427.265.19 1.45.275 1.696.07.152-.125.236-.939.053-1.031.117.116-.618.125-.686.099-.122-.044-.235.115-.43.025.117.055-.651-.358-.22-.674-.181.132-.349-.037-.544.109-.135.109.062.181-.13.277-.305.155-.535-.53-.649-.607-.118-.077-1.024-.713-.777-.298l.797.793c-.04.026-.209-.289-.209-.059.053-.136.02.585-.105.35-.056-.09.091-.14.006-.271 0-.085-.23-.169-.275-.228-.126-.157-.462-.502-.644-.585-.05-.024-.771.088-.832.111-.071.099-.131.203-.181.314-.149.055-.29.127-.423.216l-.159.356c-.068.061-.772.294-.776.303.03-.076-.492-.172-.457-.324.038-.167.215-.687.169-.877-.048-.199 1.085.287 1.158-.238.029-.227.047-.492-.316-.531.069.008.702-.249.807-.364.148-.169.486-.447.731-.447.286 0 .225-.417.356-.622.133.053-.071.38.088.512-.01-.104.45.057.494.033.105-.056.691-.023.601-.299-.101-.28.052-.197.183-.255-.02.008.248-.458.363-.456-.104-.089-.398.112-.516.103-.308-.024-.177-.525-.061-.672.09-.116-.246-.258-.25-.036-.006.332-.314.633-.243 1.075.109.666-.743-.161-.816-.115-.283.172-.515-.216-.368-.449.149-.238.51-.226.659-.48.104-.179.227-.389.388-.524.541-.454.689-.091 1.229-.042.526.048.178.125.105.327-.07.192.289.261.413.1.071-.092.232-.326.301-.499.07-.175.578-.2.527-.365 2.72 1.148 4.827 3.465 5.694 6.318zm-11.113-3.779l.068-.087.073-.019c.042-.034.086-.118.151-.104.043.009.146.095.111.148-.037.054-.066-.049-.081.101-.018.169-.188.167-.313.222-.087.037-.175-.018-.09-.104l.088-.108-.007-.049zm.442.245c.046-.045.138-.008.151-.094.014-.084.078-.178-.008-.335-.022-.042.116-.082.051-.137l-.109.032s.155-.668.364-.366l-.089.103c.135.134.172.47.215.687.127.066.324.078.098.192.117-.02-.618.314-.715.178-.072-.083.317-.139.307-.173-.004-.011-.317-.02-.265-.087zm1.43-3.547l-.356.326c-.36.298-1.28.883-1.793.705-.524-.18-1.647.667-1.826.673-.067.003.002-.641.36-.689-.141.021.993-.575 1.185-.805.678-.146 1.381-.227 2.104-.227l.326.017zm-5.086 1.19c.07.082.278.092-.026.288-.183.11-.377.809-.548.809-.51.223-.542-.439-1.109.413-.078.115-.395.158-.644.236.685-.688 1.468-1.279 2.327-1.746zm-5.24 8.793c0-.541.055-1.068.139-1.586l.292.185c.113.135.113.719.169.911.139.482.484.751.748 1.19.155.261.414.923.332 1.197.109-.179 1.081.824 1.259 1.033.418.492.74 1.088.061 1.574-.219.158.334 1.14.049 1.382l-.365.094c-.225.138-.235.397-.166.631-1.562-1.765-2.518-4.076-2.518-6.611zm14.347-5.823c.083-.01-.107.167-.107.167.033.256.222.396.581.527.437.157.038.455-.213.385-.139-.039-.854-.255-.879.025 0 .167-.679.001-.573-.175.073-.119.05-.387.186-.562.193-.255.38-.116.386.032-.001.394.398-.373.619-.399z" fill="currentColor"/></svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

@ -0,0 +1,10 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2344_20)">
<path d="M0 0V24H24V0H0ZM8 19H5V8H8V19ZM6.5 6.732C5.534 6.732 4.75 5.942 4.75 4.968C4.75 3.994 5.534 3.204 6.5 3.204C7.466 3.204 8.25 3.994 8.25 4.968C8.25 5.942 7.467 6.732 6.5 6.732ZM20 19H17V13.396C17 10.028 13 10.283 13 13.396V19H10V8H13V9.765C14.397 7.179 20 6.988 20 12.241V19Z" fill="currentColor"/>
</g>
<defs>
<clipPath id="clip0_2344_20">
<rect width="24" height="24" rx="2" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 611 B

@ -0,0 +1,73 @@
import type { MarkdownFileType } from './file';
export interface AuthorFrontmatter {
name: string;
imageUrl: string;
social: {
twitter: string;
github: string;
linkedin: string;
website: string;
};
}
export type AuthorFileType = MarkdownFileType<AuthorFrontmatter> & {
id: string;
};
function authorPathToId(filePath: string): string {
const fileName = filePath.split('/').pop() || '';
return fileName.replace('.md', '');
}
/**
* Gets the IDs of all the authors available on the website
*
* @returns string[] Array of author IDs
*/
export async function getAuthorIds() {
const authorFiles = import.meta.glob<AuthorFileType>(
'/src/data/authors/*.md',
{
eager: true,
},
);
console.log(Object.keys(authorFiles));
return Object.keys(authorFiles).map(authorPathToId);
}
export async function getAllAuthors(): Promise<AuthorFileType[]> {
const authorFilesMap: Record<string, AuthorFileType> =
import.meta.glob<AuthorFileType>('/src/data/authors/*.md', {
eager: true,
});
const authorFiles = Object.values(authorFilesMap);
return authorFiles.map((authorFile) => ({
...authorFile,
id: authorPathToId(authorFile.file),
}));
}
export async function getAuthorById(id: string): Promise<AuthorFileType> {
const authorFilesMap: Record<string, AuthorFileType> =
import.meta.glob<AuthorFileType>('/src/data/authors/*.md', {
eager: true,
});
const authorFile = Object.values(authorFilesMap).find((authorFile) => {
return authorPathToId(authorFile.file) === id;
});
if (!authorFile) {
throw new Error(`Author with ID ${id} not found`);
}
return {
...authorFile,
id: authorPathToId(authorFile.file),
};
}

@ -1,13 +1,10 @@
import type { MarkdownFileType } from './file';
import { type AuthorFileType, getAllAuthors } from './author.ts';
export interface GuideFrontmatter {
title: string;
description: string;
author: {
name: string;
url: string;
imageUrl: string;
};
authorId: string;
canonicalUrl?: string;
// alternate path where this guide has been published
excludedBySlug?: string;
@ -27,6 +24,7 @@ export interface GuideFrontmatter {
export type GuideFileType = MarkdownFileType<GuideFrontmatter> & {
id: string;
author: AuthorFileType;
};
/**
@ -41,23 +39,33 @@ function guidePathToId(filePath: string): string {
return fileName.replace('.md', '');
}
export async function getGuidesByAuthor(
authorId: string,
): Promise<GuideFileType[]> {
const allGuides = await getAllGuides();
return allGuides.filter((guide) => guide.author?.id === authorId);
}
/**
* Gets all the guides sorted by the publishing date
* @returns Promisifed guide files
*/
export async function getAllGuides(): Promise<GuideFileType[]> {
// @ts-ignore
const guides = await import.meta.glob<GuideFileType>(
'/src/data/guides/*.md',
{
eager: true,
},
);
const guides = import.meta.glob<GuideFileType>('/src/data/guides/*.md', {
eager: true,
});
const allAuthors = await getAllAuthors();
const guideFiles = Object.values(guides) as GuideFileType[];
const enrichedGuides = guideFiles.map((guideFile) => ({
const enrichedGuides: GuideFileType[] = guideFiles.map((guideFile) => ({
...guideFile,
id: guidePathToId(guideFile.file),
author: allAuthors.find(
(author) => author.id === guideFile.frontmatter.authorId,
)!,
}));
return enrichedGuides.sort(

@ -60,7 +60,7 @@ function roadmapPathToId(filePath: string): string {
* @returns string[] Array of roadmap IDs
*/
export async function getRoadmapIds() {
const roadmapFiles = await import.meta.glob<RoadmapFileType>(
const roadmapFiles = import.meta.glob<RoadmapFileType>(
'/src/data/roadmaps/*/*.md',
{
eager: true,
@ -79,14 +79,14 @@ export async function getRoadmapIds() {
export async function getRoadmapsByTag(
tag: string,
): Promise<RoadmapFileType[]> {
const roadmapFilesMap = await import.meta.glob<RoadmapFileType>(
const roadmapFilesMap = import.meta.glob<RoadmapFileType>(
'/src/data/roadmaps/*/*.md',
{
eager: true,
},
);
const roadmapFiles = Object.values(roadmapFilesMap);
const roadmapFiles: RoadmapFileType[] = Object.values(roadmapFilesMap);
const filteredRoadmaps = roadmapFiles
.filter((roadmapFile) => roadmapFile.frontmatter.tags.includes(tag))
.map((roadmapFile) => ({
@ -100,12 +100,10 @@ export async function getRoadmapsByTag(
}
export async function getRoadmapById(id: string): Promise<RoadmapFileType> {
const roadmapFilesMap = await import.meta.glob<RoadmapFileType>(
'/src/data/roadmaps/*/*.md',
{
const roadmapFilesMap: Record<string, RoadmapFileType> =
import.meta.glob<RoadmapFileType>('/src/data/roadmaps/*/*.md', {
eager: true,
},
);
});
const roadmapFile = Object.values(roadmapFilesMap).find((roadmapFile) => {
return roadmapPathToId(roadmapFile.file) === id;

@ -1,4 +1,5 @@
import type { MarkdownFileType } from './file';
import type {AuthorFileType} from "./author.ts";
export interface VideoFrontmatter {
title: string;
@ -17,13 +18,14 @@ export interface VideoFrontmatter {
date: string;
sitemap: {
priority: number;
changefreq: 'daily' | 'weekly' | 'monthly' | 'yealry';
changefreq: 'daily' | 'weekly' | 'monthly' | 'yearly';
};
tags: string[];
}
export type VideoFileType = MarkdownFileType<VideoFrontmatter> & {
id: string;
author: AuthorFileType;
};
/**
@ -43,12 +45,9 @@ function videoPathToId(filePath: string): string {
* @returns Promisifed video files
*/
export async function getAllVideos(): Promise<VideoFileType[]> {
const videos = await import.meta.glob<VideoFileType>(
'/src/data/videos/*.md',
{
eager: true,
}
);
const videos = import.meta.glob<VideoFileType>('/src/data/videos/*.md', {
eager: true,
});
const videoFiles = Object.values(videos);
const enrichedVideos = videoFiles.map((videoFile) => ({
@ -59,6 +58,6 @@ export async function getAllVideos(): Promise<VideoFileType[]> {
return enrichedVideos.sort(
(a, b) =>
new Date(b.frontmatter.date).valueOf() -
new Date(a.frontmatter.date).valueOf()
new Date(a.frontmatter.date).valueOf(),
);
}

@ -0,0 +1,110 @@
---
import BaseLayout from '../../layouts/BaseLayout.astro';
import AstroIcon from '../../components/AstroIcon.astro';
import { getGuidesByAuthor } from '../../lib/guide';
import { getAllVideos } from '../../lib/video';
import GuideListItem from '../../components/GuideListItem.astro';
import { getAuthorById, getAuthorIds } from '../../lib/author';
interface Params extends Record<string, string | undefined> {}
export async function getStaticPaths() {
const authorIds = await getAuthorIds();
return authorIds.map((authorId) => ({
params: { authorId },
}));
}
const { authorId } = Astro.params;
const author = await getAuthorById(authorId);
const guides = await getGuidesByAuthor(authorId);
const videos = await getAllVideos();
---
<BaseLayout
permalink={`/author/${author.id}`}
title={`${author.frontmatter.name} - Author at roadmap.sh`}
briefTitle={author.frontmatter.name}
ogImageUrl={`https://roadmap.sh/${author.frontmatter.imageUrl}`}
description={`${author.frontmatter.name} has written ${guides.length} articles on roadmap.sh on a variety of topics.`}
noIndex={false}
>
<div class='container pt-4 pb-0 md:pb-16 md:pt-8'>
<div class=''>
<div class='mb-5 flex items-center gap-8 rounded-3xl py-0 md:py-8'>
<div>
<h1 class='text-2xl md:text-3xl font-bold'>{author.frontmatter.name}</h1>
<div
class='mt-1 mb-4 md:mt-4 md:mb-6 flex flex-col gap-3 text-gray-800 [&>p>a]:font-semibold [&>p>a]:underline leading-normal'
>
<author.Content />
</div>
<div class='flex items-center justify-between'>
<div class='flex items-center gap-1.5'>
{
author.frontmatter.social?.github && (
<a
href={author.frontmatter.social.github}
target='_blank'
class='text-gray-500 transition-colors hover:text-gray-800'
>
<AstroIcon icon='github' class='h-[20px]' />
</a>
)
}
{
author.frontmatter.social.twitter && (
<a
href={author.frontmatter.social.twitter}
target='_blank'
class='text-gray-500 transition-colors hover:text-gray-800'
>
<AstroIcon icon='twitter' class='h-[20px]' />
</a>
)
}
{
author.frontmatter.social.linkedin && (
<a
href={author.frontmatter.social.linkedin}
target='_blank'
class='text-gray-500 transition-colors hover:text-gray-800'
>
<AstroIcon icon='linkedin-2' class='h-[20px]' />
</a>
)
}
{
author.frontmatter.social.website && (
<a
href={author.frontmatter.social.website}
target='_blank'
class='text-gray-500 transition-colors hover:text-gray-800'
>
<AstroIcon icon='globe' class='h-[20px]' />
</a>
)
}
</div>
</div>
</div>
<div class='hidden flex-shrink-0 flex-col md:flex'>
<img
alt="Kamran Ahmed's profile picture"
class='block h-[175px] w-[175px] rounded-full bg-gray-100'
src={author.frontmatter.imageUrl}
/>
</div>
</div>
</div>
<div
class='rounded-t-xl bg-gradient-to-b from-gray-100 to-white px-3 py-2 md:px-6 md:py-3 [&>*:last-child]:border-b-0'
>
{guides.map((guide) => <GuideListItem guide={guide} />)}
</div>
</div>
</BaseLayout>
Loading…
Cancel
Save