feat: add custom renderer for roadmaps (#5691)

* wip

* fix: update packages

* wip

* wip

* feat: editor content generator

* fix: add dimensions

* feat: add renderer

* feat: add progress modal renderer

* Add API design roadmap

* Update API roadmap rendering

* fix: button click

* fix: link item

* feat: render pdf for editor roadmaps

* Add API roadmap

* Fix broken link of full-stack roadmap

* Update content dir

* Fix typos in api roadmap

* Add assets for pdf and svg

* Add content for api roadmap

* Add todo

* fix: close on editor roadmap select

* Update link not working

* Add api roadmap to get-started and roadmaps page

---------

Co-authored-by: Arik Chakma <arikchangma@gmail.com>
pull/5693/head
Kamran Ahmed 6 months ago committed by GitHub
parent 375ad931f7
commit 5e50ffbc30
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      astro.config.mjs
  2. 12
      package.json
  3. 159
      pnpm-lock.yaml
  4. BIN
      public/pdfs/roadmaps/api.pdf
  5. BIN
      public/roadmaps/api.png
  6. 75
      scripts/editor-roadmap-assets.ts
  7. 185
      scripts/editor-roadmap-content.ts
  8. 86
      scripts/editor-roadmap-dirs.ts
  9. 2
      src/components/CommandMenu/CommandMenu.tsx
  10. 6
      src/components/CreateTeam/RoadmapSelector.tsx
  11. 85
      src/components/EditorRoadmap/EditorRoadmap.tsx
  12. 56
      src/components/EditorRoadmap/EditorRoadmapRenderer.css
  13. 176
      src/components/EditorRoadmap/EditorRoadmapRenderer.tsx
  14. 12
      src/components/FrameRenderer/FrameRenderer.css
  15. 23
      src/components/Friends/FriendProgressItem.tsx
  16. 15
      src/components/Friends/FriendsPage.tsx
  17. 15
      src/components/RelatedRoadmaps.astro
  18. 4
      src/components/RoadmapHint.astro
  19. 6
      src/components/Roadmaps/RoadmapsPage.tsx
  20. 4
      src/components/TeamActivity/TeamActivityPage.tsx
  21. 14
      src/components/TeamMemberDetails/TeamMemberDetailsPage.tsx
  22. 10
      src/components/TeamRoadmapsList/TeamRoadmaps.tsx
  23. 4
      src/components/TeamVersions/TeamVersions.tsx
  24. 5
      src/components/TopicDetail/TopicDetail.tsx
  25. 18
      src/components/UserProgress/UserProgressModal.tsx
  26. 1
      src/data/roadmaps/api/api.json
  27. 63
      src/data/roadmaps/api/api.md
  28. 3
      src/data/roadmaps/api/content/api-documentation-tools@5R9yKfN1vItuv__HgCwP7.md
  29. 3
      src/data/roadmaps/api/content/api-gateways@MJeUD4fOHaJu1oxk4uQ-x.md
  30. 3
      src/data/roadmaps/api/content/api-integration-patterns@R3aRhqCslwhegMfHtxg5z.md
  31. 3
      src/data/roadmaps/api/content/api-keys--management@tzUJwXu_scwQHnPPT0oY-.md
  32. 3
      src/data/roadmaps/api/content/api-lifecycle-management@At5exN7ZAx2IzY3cTCzHm.md
  33. 3
      src/data/roadmaps/api/content/api-performance@d9ZXdU73jiCdeNHQv1_DH.md
  34. 3
      src/data/roadmaps/api/content/api-security@qIJ6dUppjAjOTA8eQbp0n.md
  35. 3
      src/data/roadmaps/api/content/api-testing@Wpk4TvxcZOJgAoXjrOsZF.md
  36. 3
      src/data/roadmaps/api/content/attribute-based-access-control-abac@dZTe_kxIUQsc9N3w920aR.md
  37. 3
      src/data/roadmaps/api/content/authentication-methods@cQnQ9v3mH27MGNwetz3JW.md
  38. 3
      src/data/roadmaps/api/content/authorization-methods@nHbn8_sMY7J8o6ckbD-ER.md
  39. 3
      src/data/roadmaps/api/content/basic-auth@0FzHERK5AeYL5wv1FBJbH.md
  40. 3
      src/data/roadmaps/api/content/basics-of-dns@v4nJYD9yiIEUviLPhVTCD.md
  41. 3
      src/data/roadmaps/api/content/batch-processing@X68HXAAV-nKo-V4Fu1o72.md
  42. 3
      src/data/roadmaps/api/content/best-practices@q1yaf-RbHIQsOqfzjn4k4.md
  43. 3
      src/data/roadmaps/api/content/building-json--restful-apis@awdoiCHz7Yc3kYac_iy-a.md
  44. 3
      src/data/roadmaps/api/content/caching-strategies@PrvRCR4HCdGar0vcUbG_a.md
  45. 3
      src/data/roadmaps/api/content/ccpa@a-_iIE7UdoXzD00fD9MxN.md
  46. 3
      src/data/roadmaps/api/content/common-vulnerabilities@G70wvcOM1Isrx5ZBvS2xP.md
  47. 3
      src/data/roadmaps/api/content/content-negotiation@TX_hg7EobNJhmWKsMCaT1.md
  48. 3
      src/data/roadmaps/api/content/contract-testing@NqeBglhzukVMMEF9p2CXc.md
  49. 3
      src/data/roadmaps/api/content/cookies@UFuX8wcxZQ7dvaQF_2Yp8.md
  50. 3
      src/data/roadmaps/api/content/cors@GRlsBogOlOwuqhMMPyHN3.md
  51. 3
      src/data/roadmaps/api/content/different-api-styles@o8i093VQv-T5Qf1yGqU0R.md
  52. 5
      src/data/roadmaps/api/content/error-handling--retries@XD1vDtrRQFbLyKJaD1AlA.md
  53. 3
      src/data/roadmaps/api/content/error-handling@8tELdagrOaGCf3nMVs8t3.md
  54. 3
      src/data/roadmaps/api/content/event-driven-architecture@oMfOBkVsgiLvFLicOUdx6.md
  55. 3
      src/data/roadmaps/api/content/functional-testing@6lm3wy9WTAERTqXCn6pFt.md
  56. 3
      src/data/roadmaps/api/content/gdpr@vZxdswGLHCPi5GSuXEcHJ.md
  57. 3
      src/data/roadmaps/api/content/graphql-apis@MKVcPM2EzAr2_Ieyp9Fu3.md
  58. 5
      src/data/roadmaps/api/content/handling-crud-operations@zXxEiM5HeOn7W-Vue0tQf.md
  59. 3
      src/data/roadmaps/api/content/hateoas@LByD1vhzunhY1uY1YGZHP.md
  60. 3
      src/data/roadmaps/api/content/hipaa@W4WwTmgZGnWmiYsB0ezml.md
  61. 3
      src/data/roadmaps/api/content/http-caching@qAolZHf_jp8hCdtqHZwC8.md
  62. 3
      src/data/roadmaps/api/content/http-headers@rE-0yibRH6B2UBKp351cf.md
  63. 3
      src/data/roadmaps/api/content/http-methods@rADHM-6NAxEjzmgiHefDX.md
  64. 3
      src/data/roadmaps/api/content/http-status-codes@7szYyzLifKsepNU0c2KnN.md
  65. 3
      src/data/roadmaps/api/content/http-versions@ACALE93mL4gnX5ThRIdRp.md
  66. 3
      src/data/roadmaps/api/content/http@2HdKzAIQi15pr3YHHrbPp.md
  67. 3
      src/data/roadmaps/api/content/idempotency@20KEgZH6cu_UokqWpV-9I.md
  68. 3
      src/data/roadmaps/api/content/integration-testing@qZELS5vw2feS7QfyD7spX.md
  69. 3
      src/data/roadmaps/api/content/jwt@tWg68AHLIr1gIZA1za3jp.md
  70. 3
      src/data/roadmaps/api/content/kafka@boYX1QcJullypfX4sevdy.md
  71. 3
      src/data/roadmaps/api/content/learn-the-basics@duKkpzPjUU_-8kyJGHqRX.md
  72. 3
      src/data/roadmaps/api/content/load-balancing@p5wsniYnOS7cbHd92RxGk.md
  73. 3
      src/data/roadmaps/api/content/load-testing@7JNEx_cbqnAx3esvwZMOd.md
  74. 3
      src/data/roadmaps/api/content/messaging-queues@IkPZel5zxXWIx90Qx7fZI.md
  75. 3
      src/data/roadmaps/api/content/microservices-architecture@PPeBbooE121zrgNwpVTiA.md
  76. 3
      src/data/roadmaps/api/content/mocking-apis@bEVCT5QGY3uw0kIfAELKh.md
  77. 3
      src/data/roadmaps/api/content/oauth-20@TLuNtQ6HKYQXmglyVk8-t.md
  78. 3
      src/data/roadmaps/api/content/pagination@pgJDzP3pJjhjr5wTRtPJO.md
  79. 3
      src/data/roadmaps/api/content/pci-dss@J0enF8UTVzY3H4n3pbPIF.md
  80. 3
      src/data/roadmaps/api/content/performance-metrics@nQpczZUcn-TvrfT80dv0Q.md
  81. 3
      src/data/roadmaps/api/content/performance-testing@DQcAV59vr1-ZRnMfbLXpu.md
  82. 3
      src/data/roadmaps/api/content/pii@mXCKtLUvwVJkHrpHzOecq.md
  83. 3
      src/data/roadmaps/api/content/postman@KQAus72RGqx5f-3-YeJby.md
  84. 3
      src/data/roadmaps/api/content/profiling-and-monitoring@-qdwBg7HvwlbLy3IKCRij.md
  85. 5
      src/data/roadmaps/api/content/rabbit-mq@H22jAI2W5QLL-b1rq-c56.md
  86. 3
      src/data/roadmaps/api/content/rate-limiting--throttling@tPVtRV818D8zAAuNbqPNa.md
  87. 3
      src/data/roadmaps/api/content/readmecom@LxWHkhlikUaMT2G8YmVDQ.md
  88. 3
      src/data/roadmaps/api/content/real-time-apis@JE12g5cqnwmgeTle14Vxw.md
  89. 3
      src/data/roadmaps/api/content/reate-limiting@O7wjldZ3yTA2s_F-UnJw_.md
  90. 3
      src/data/roadmaps/api/content/rest-principles@9WI_z34jIFXwoUQuChyRU.md
  91. 3
      src/data/roadmaps/api/content/restful-apis@BvwdASMvuNQ9DNgzdSZ4o.md
  92. 3
      src/data/roadmaps/api/content/rfc-7807----problem-details-for-apis@5CxU3inGcSHp-TDg3BQiY.md
  93. 3
      src/data/roadmaps/api/content/role-based-access-control-rbac@wFsbmMi5Ey9UyDADdbdPW.md
  94. 3
      src/data/roadmaps/api/content/server-sent-events@iNsXTtcIHsI_i-mCfjGYn.md
  95. 7
      src/data/roadmaps/api/content/session-based-auth@eQWoy4CpYP3TJL2bbhPB_.md
  96. 3
      src/data/roadmaps/api/content/simple-json-apis@TVR-SkErlOHbDKLBGfxep.md
  97. 3
      src/data/roadmaps/api/content/soap-apis@Wwd-0PjrtViMFWxRGaQey.md
  98. 7
      src/data/roadmaps/api/content/standards-and-compliance@yvdfoly5WHHTq2Puss355.md
  99. 3
      src/data/roadmaps/api/content/stoplight@OpS2NX1lPTOtfjV1wKtC4.md
  100. 3
      src/data/roadmaps/api/content/swagger--open-api@5RY7AlfRQydjxWK65Z4cv.md
  101. Some files were not shown because too many files have changed in this diff Show More

@ -11,6 +11,9 @@ import react from '@astrojs/react';
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
site: 'https://roadmap.sh/', site: 'https://roadmap.sh/',
experimental: {
rewriting: true,
},
markdown: { markdown: {
shikiConfig: { shikiConfig: {
theme: 'dracula', theme: 'dracula',

@ -15,6 +15,9 @@
"upgrade": "ncu -u", "upgrade": "ncu -u",
"roadmap-links": "node scripts/roadmap-links.cjs", "roadmap-links": "node scripts/roadmap-links.cjs",
"roadmap-dirs": "node scripts/roadmap-dirs.cjs", "roadmap-dirs": "node scripts/roadmap-dirs.cjs",
"roadmap-assets": "tsx scripts/editor-roadmap-assets.ts",
"editor-roadmap-dirs": "tsx scripts/editor-roadmap-dirs.ts",
"editor-roadmap-content": "tsx scripts/editor-roadmap-content.ts",
"roadmap-content": "node scripts/roadmap-content.cjs", "roadmap-content": "node scripts/roadmap-content.cjs",
"generate-renderer": "sh scripts/generate-renderer.sh", "generate-renderer": "sh scripts/generate-renderer.sh",
"best-practice-dirs": "node scripts/best-practice-dirs.cjs", "best-practice-dirs": "node scripts/best-practice-dirs.cjs",
@ -35,7 +38,7 @@
"@resvg/resvg-js": "^2.6.2", "@resvg/resvg-js": "^2.6.2",
"@types/react": "^18.3.2", "@types/react": "^18.3.2",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"astro": "^4.8.3", "astro": "^4.8.5",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"dayjs": "^1.11.11", "dayjs": "^1.11.11",
"dom-to-image": "^2.6.0", "dom-to-image": "^2.6.0",
@ -50,6 +53,7 @@
"nanostores": "^0.10.3", "nanostores": "^0.10.3",
"node-html-parser": "^6.1.13", "node-html-parser": "^6.1.13",
"npm-check-updates": "^16.14.20", "npm-check-updates": "^16.14.20",
"playwright": "^1.44.0",
"prismjs": "^1.29.0", "prismjs": "^1.29.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-calendar-heatmap": "^1.9.0", "react-calendar-heatmap": "^1.9.0",
@ -62,7 +66,7 @@
"roadmap-renderer": "^1.0.6", "roadmap-renderer": "^1.0.6",
"satori": "^0.10.13", "satori": "^0.10.13",
"satori-html": "^0.3.2", "satori-html": "^0.3.2",
"sharp": "^0.33.3", "sharp": "^0.33.4",
"slugify": "^1.6.6", "slugify": "^1.6.6",
"tailwind-merge": "^2.3.0", "tailwind-merge": "^2.3.0",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
@ -80,10 +84,10 @@
"gh-pages": "^6.1.1", "gh-pages": "^6.1.1",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"openai": "^4.45.0", "openai": "^4.47.1",
"prettier": "^3.2.5", "prettier": "^3.2.5",
"prettier-plugin-astro": "^0.13.0", "prettier-plugin-astro": "^0.13.0",
"prettier-plugin-tailwindcss": "^0.5.14", "prettier-plugin-tailwindcss": "^0.5.14",
"tsx": "^4.10.2" "tsx": "^4.10.4"
} }
} }

@ -10,7 +10,7 @@ importers:
dependencies: dependencies:
'@astrojs/node': '@astrojs/node':
specifier: ^8.2.5 specifier: ^8.2.5
version: 8.2.5(astro@4.8.3(@types/node@18.19.31)) version: 8.2.5(astro@4.8.5(@types/node@18.19.31))
'@astrojs/react': '@astrojs/react':
specifier: ^3.3.4 specifier: ^3.3.4
version: 3.3.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(vite@5.2.11(@types/node@18.19.31)) version: 3.3.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(vite@5.2.11(@types/node@18.19.31))
@ -19,7 +19,7 @@ importers:
version: 3.1.4 version: 3.1.4
'@astrojs/tailwind': '@astrojs/tailwind':
specifier: ^5.1.0 specifier: ^5.1.0
version: 5.1.0(astro@4.8.3(@types/node@18.19.31))(tailwindcss@3.4.3) version: 5.1.0(astro@4.8.5(@types/node@18.19.31))(tailwindcss@3.4.3)
'@fingerprintjs/fingerprintjs': '@fingerprintjs/fingerprintjs':
specifier: ^4.3.0 specifier: ^4.3.0
version: 4.3.0 version: 4.3.0
@ -39,8 +39,8 @@ importers:
specifier: ^18.3.0 specifier: ^18.3.0
version: 18.3.0 version: 18.3.0
astro: astro:
specifier: ^4.8.3 specifier: ^4.8.5
version: 4.8.3(@types/node@18.19.31) version: 4.8.5(@types/node@18.19.31)
clsx: clsx:
specifier: ^2.1.1 specifier: ^2.1.1
version: 2.1.1 version: 2.1.1
@ -83,6 +83,9 @@ importers:
npm-check-updates: npm-check-updates:
specifier: ^16.14.20 specifier: ^16.14.20
version: 16.14.20 version: 16.14.20
playwright:
specifier: ^1.44.0
version: 1.44.0
prismjs: prismjs:
specifier: ^1.29.0 specifier: ^1.29.0
version: 1.29.0 version: 1.29.0
@ -120,8 +123,8 @@ importers:
specifier: ^0.3.2 specifier: ^0.3.2
version: 0.3.2 version: 0.3.2
sharp: sharp:
specifier: ^0.33.3 specifier: ^0.33.4
version: 0.33.3 version: 0.33.4
slugify: slugify:
specifier: ^1.6.6 specifier: ^1.6.6
version: 1.6.6 version: 1.6.6
@ -169,8 +172,8 @@ importers:
specifier: ^14.1.0 specifier: ^14.1.0
version: 14.1.0 version: 14.1.0
openai: openai:
specifier: ^4.45.0 specifier: ^4.47.1
version: 4.45.0(encoding@0.1.13) version: 4.47.1(encoding@0.1.13)
prettier: prettier:
specifier: ^3.2.5 specifier: ^3.2.5
version: 3.2.5 version: 3.2.5
@ -181,8 +184,8 @@ importers:
specifier: ^0.5.14 specifier: ^0.5.14
version: 0.5.14(prettier-plugin-astro@0.13.0)(prettier@3.2.5) version: 0.5.14(prettier-plugin-astro@0.13.0)(prettier@3.2.5)
tsx: tsx:
specifier: ^4.10.2 specifier: ^4.10.4
version: 4.10.2 version: 4.10.4
packages: packages:
@ -704,14 +707,14 @@ packages:
'@gar/promisify@1.1.3': '@gar/promisify@1.1.3':
resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
'@img/sharp-darwin-arm64@0.33.3': '@img/sharp-darwin-arm64@0.33.4':
resolution: {integrity: sha512-FaNiGX1MrOuJ3hxuNzWgsT/mg5OHG/Izh59WW2mk1UwYHUwtfbhk5QNKYZgxf0pLOhx9ctGiGa2OykD71vOnSw==} resolution: {integrity: sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==}
engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@img/sharp-darwin-x64@0.33.3': '@img/sharp-darwin-x64@0.33.4':
resolution: {integrity: sha512-2QeSl7QDK9ru//YBT4sQkoq7L0EAJZA3rtV+v9p8xTKl4U1bUqTIaCnoC7Ctx2kCjQgwFXDasOtPTCT8eCTXvw==} resolution: {integrity: sha512-0l7yRObwtTi82Z6ebVI2PnHT8EB2NxBgpK2MiKJZJ7cz32R4lxd001ecMhzzsZig3Yv9oclvqqdV93jo9hy+Dw==}
engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
@ -764,55 +767,55 @@ packages:
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@img/sharp-linux-arm64@0.33.3': '@img/sharp-linux-arm64@0.33.4':
resolution: {integrity: sha512-Zf+sF1jHZJKA6Gor9hoYG2ljr4wo9cY4twaxgFDvlG0Xz9V7sinsPp8pFd1XtlhTzYo0IhDbl3rK7P6MzHpnYA==} resolution: {integrity: sha512-2800clwVg1ZQtxwSoTlHvtm9ObgAax7V6MTAB/hDT945Tfyy3hVkmiHpeLPCKYqYR1Gcmv1uDZ3a4OFwkdBL7Q==}
engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@img/sharp-linux-arm@0.33.3': '@img/sharp-linux-arm@0.33.4':
resolution: {integrity: sha512-Q7Ee3fFSC9P7vUSqVEF0zccJsZ8GiiCJYGWDdhEjdlOeS9/jdkyJ6sUSPj+bL8VuOYFSbofrW0t/86ceVhx32w==} resolution: {integrity: sha512-RUgBD1c0+gCYZGCCe6mMdTiOFS0Zc/XrN0fYd6hISIKcDUbAW5NtSQW9g/powkrXYm6Vzwd6y+fqmExDuCdHNQ==}
engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@img/sharp-linux-s390x@0.33.3': '@img/sharp-linux-s390x@0.33.4':
resolution: {integrity: sha512-vFk441DKRFepjhTEH20oBlFrHcLjPfI8B0pMIxGm3+yilKyYeHEVvrZhYFdqIseSclIqbQ3SnZMwEMWonY5XFA==} resolution: {integrity: sha512-h3RAL3siQoyzSoH36tUeS0PDmb5wINKGYzcLB5C6DIiAn2F3udeFAum+gj8IbA/82+8RGCTn7XW8WTFnqag4tQ==}
engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} engines: {glibc: '>=2.31', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
'@img/sharp-linux-x64@0.33.3': '@img/sharp-linux-x64@0.33.4':
resolution: {integrity: sha512-Q4I++herIJxJi+qmbySd072oDPRkCg/SClLEIDh5IL9h1zjhqjv82H0Seupd+q2m0yOfD+/fJnjSoDFtKiHu2g==} resolution: {integrity: sha512-GoR++s0XW9DGVi8SUGQ/U4AeIzLdNjHka6jidVwapQ/JebGVQIpi52OdyxCNVRE++n1FCLzjDovJNozif7w/Aw==}
engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@img/sharp-linuxmusl-arm64@0.33.3': '@img/sharp-linuxmusl-arm64@0.33.4':
resolution: {integrity: sha512-qnDccehRDXadhM9PM5hLvcPRYqyFCBN31kq+ErBSZtZlsAc1U4Z85xf/RXv1qolkdu+ibw64fUDaRdktxTNP9A==} resolution: {integrity: sha512-nhr1yC3BlVrKDTl6cO12gTpXMl4ITBUZieehFvMntlCXFzH2bvKG76tBL2Y/OqhupZt81pR7R+Q5YhJxW0rGgQ==}
engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@img/sharp-linuxmusl-x64@0.33.3': '@img/sharp-linuxmusl-x64@0.33.4':
resolution: {integrity: sha512-Jhchim8kHWIU/GZ+9poHMWRcefeaxFIs9EBqf9KtcC14Ojk6qua7ghKiPs0sbeLbLj/2IGBtDcxHyjCdYWkk2w==} resolution: {integrity: sha512-uCPTku0zwqDmZEOi4ILyGdmW76tH7dm8kKlOIV1XC5cLyJ71ENAAqarOHQh0RLfpIpbV5KOpXzdU6XkJtS0daw==}
engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@img/sharp-wasm32@0.33.3': '@img/sharp-wasm32@0.33.4':
resolution: {integrity: sha512-68zivsdJ0koE96stdUfM+gmyaK/NcoSZK5dV5CAjES0FUXS9lchYt8LAB5rTbM7nlWtxaU/2GON0HVN6/ZYJAQ==} resolution: {integrity: sha512-Bmmauh4sXUsUqkleQahpdNXKvo+wa1V9KhT2pDA4VJGKwnKMJXiSTGphn0gnJrlooda0QxCtXc6RX1XAU6hMnQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [wasm32] cpu: [wasm32]
'@img/sharp-win32-ia32@0.33.3': '@img/sharp-win32-ia32@0.33.4':
resolution: {integrity: sha512-CyimAduT2whQD8ER4Ux7exKrtfoaUiVr7HG0zZvO0XTFn2idUWljjxv58GxNTkFb8/J9Ub9AqITGkJD6ZginxQ==} resolution: {integrity: sha512-99SJ91XzUhYHbx7uhK3+9Lf7+LjwMGQZMDlO/E/YVJ7Nc3lyDFZPGhjwiYdctoH2BOzW9+TnfqcaMKt0jHLdqw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
'@img/sharp-win32-x64@0.33.3': '@img/sharp-win32-x64@0.33.4':
resolution: {integrity: sha512-viT4fUIDKnli3IfOephGnolMzhz5VaTvDRkYqtZxOMIoMQ4MrAziO7pT1nVnOt2FAm7qW5aa+CCc13aEY6Le0g==} resolution: {integrity: sha512-3QLocdTRVIrFNye5YocZl+KKpYKP+fksi1QhmOArgx7GyhIbQp/WrJRu176jm8IxromS7RIkzMiMINVdBtC8Aw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
@ -1506,8 +1509,8 @@ packages:
resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
astro@4.8.3: astro@4.8.5:
resolution: {integrity: sha512-pgIKopkmAUXY3EJHdG7zQpudtBzYAsd94A1R7jmLpH2LFZvzHEkAdHnunmSVmgikJCNqtEo3bUCHgLnCPQaN1g==} resolution: {integrity: sha512-h+t4VGLPBk6KjIiJnYGotJ16wsLIdmNVSvnwEk51XhqZ5T2VlbozgDtgDi6y3qP3mqkhpN3Q39YQORhVeuEYsg==}
engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'}
hasBin: true hasBin: true
@ -2155,8 +2158,8 @@ packages:
resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
engines: {node: '>=16'} engines: {node: '>=16'}
get-tsconfig@4.7.3: get-tsconfig@4.7.5:
resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==}
gh-pages@6.1.1: gh-pages@6.1.1:
resolution: {integrity: sha512-upnohfjBwN5hBP9w2dPE7HO5JJTHzSGMV1JrLrHvNuqmjoYHg6TBrCcnEoorjG/e0ejbuvnwyKMdTyM40PEByw==} resolution: {integrity: sha512-upnohfjBwN5hBP9w2dPE7HO5JJTHzSGMV1JrLrHvNuqmjoYHg6TBrCcnEoorjG/e0ejbuvnwyKMdTyM40PEByw==}
@ -3032,8 +3035,8 @@ packages:
resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
openai@4.45.0: openai@4.47.1:
resolution: {integrity: sha512-uszUQrl9eQPCA9a7Zml+Eizb3mG0JDd8zUl528OM6Ccn039dqbOmUivL5s8zUM6iJMRMvNGRMXS9yuuR1Bv2sw==} resolution: {integrity: sha512-WWSxhC/69ZhYWxH/OBsLEirIjUcfpQ5+ihkXKp06hmeYXgBBIUCa9IptMzYx6NdkiOCsSGYCnTIsxaic3AjRCQ==}
hasBin: true hasBin: true
ora@8.0.1: ora@8.0.1:
@ -3586,8 +3589,8 @@ packages:
setprototypeof@1.2.0: setprototypeof@1.2.0:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
sharp@0.33.3: sharp@0.33.4:
resolution: {integrity: sha512-vHUeXJU1UvlO/BNwTpT0x/r53WkLUVxrmb5JTgW92fdFCFk0ispLMAeu/jPO2vjkXM1fYUi3K7/qcLF47pwM1A==} resolution: {integrity: sha512-7i/dt5kGl7qR4gwPRD2biwD2/SvBn3O04J77XKFgL2OnZtQw+AG9wnuS/csmu80nPRHLYE9E41fyEiG8nhH6/Q==}
engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0} engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0}
shebang-command@2.0.0: shebang-command@2.0.0:
@ -3831,8 +3834,8 @@ packages:
tslib@2.6.2: tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
tsx@4.10.2: tsx@4.10.4:
resolution: {integrity: sha512-gOfACgv1ElsIjvt7Fp0rMJKGnMGjox0JfGOfX3kmZCV/yZumaNqtHGKBXt1KgaYS9KjDOmqGeI8gHk/W7kWVZg==} resolution: {integrity: sha512-Gtg9qnZWNqC/OtcgiXfoAUdAKx3/cgKOYvEocAsv+m21MV/eKpV/WUjRXe6/sDCaGBl2/v8S6v29BpUnGMCX5A==}
engines: {node: '>=18.0.0'} engines: {node: '>=18.0.0'}
hasBin: true hasBin: true
@ -4175,9 +4178,9 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@astrojs/node@8.2.5(astro@4.8.3(@types/node@18.19.31))': '@astrojs/node@8.2.5(astro@4.8.5(@types/node@18.19.31))':
dependencies: dependencies:
astro: 4.8.3(@types/node@18.19.31) astro: 4.8.5(@types/node@18.19.31)
send: 0.18.0 send: 0.18.0
server-destroy: 1.0.1 server-destroy: 1.0.1
transitivePeerDependencies: transitivePeerDependencies:
@ -4205,9 +4208,9 @@ snapshots:
stream-replace-string: 2.0.0 stream-replace-string: 2.0.0
zod: 3.23.4 zod: 3.23.4
'@astrojs/tailwind@5.1.0(astro@4.8.3(@types/node@18.19.31))(tailwindcss@3.4.3)': '@astrojs/tailwind@5.1.0(astro@4.8.5(@types/node@18.19.31))(tailwindcss@3.4.3)':
dependencies: dependencies:
astro: 4.8.3(@types/node@18.19.31) astro: 4.8.5(@types/node@18.19.31)
autoprefixer: 10.4.19(postcss@8.4.38) autoprefixer: 10.4.19(postcss@8.4.38)
postcss: 8.4.38 postcss: 8.4.38
postcss-load-config: 4.0.2(postcss@8.4.38) postcss-load-config: 4.0.2(postcss@8.4.38)
@ -4309,7 +4312,7 @@ snapshots:
'@babel/helper-hoist-variables@7.22.5': '@babel/helper-hoist-variables@7.22.5':
dependencies: dependencies:
'@babel/types': 7.24.5 '@babel/types': 7.24.0
'@babel/helper-module-imports@7.24.3': '@babel/helper-module-imports@7.24.3':
dependencies: dependencies:
@ -4634,12 +4637,12 @@ snapshots:
'@gar/promisify@1.1.3': {} '@gar/promisify@1.1.3': {}
'@img/sharp-darwin-arm64@0.33.3': '@img/sharp-darwin-arm64@0.33.4':
optionalDependencies: optionalDependencies:
'@img/sharp-libvips-darwin-arm64': 1.0.2 '@img/sharp-libvips-darwin-arm64': 1.0.2
optional: true optional: true
'@img/sharp-darwin-x64@0.33.3': '@img/sharp-darwin-x64@0.33.4':
optionalDependencies: optionalDependencies:
'@img/sharp-libvips-darwin-x64': 1.0.2 '@img/sharp-libvips-darwin-x64': 1.0.2
optional: true optional: true
@ -4668,45 +4671,45 @@ snapshots:
'@img/sharp-libvips-linuxmusl-x64@1.0.2': '@img/sharp-libvips-linuxmusl-x64@1.0.2':
optional: true optional: true
'@img/sharp-linux-arm64@0.33.3': '@img/sharp-linux-arm64@0.33.4':
optionalDependencies: optionalDependencies:
'@img/sharp-libvips-linux-arm64': 1.0.2 '@img/sharp-libvips-linux-arm64': 1.0.2
optional: true optional: true
'@img/sharp-linux-arm@0.33.3': '@img/sharp-linux-arm@0.33.4':
optionalDependencies: optionalDependencies:
'@img/sharp-libvips-linux-arm': 1.0.2 '@img/sharp-libvips-linux-arm': 1.0.2
optional: true optional: true
'@img/sharp-linux-s390x@0.33.3': '@img/sharp-linux-s390x@0.33.4':
optionalDependencies: optionalDependencies:
'@img/sharp-libvips-linux-s390x': 1.0.2 '@img/sharp-libvips-linux-s390x': 1.0.2
optional: true optional: true
'@img/sharp-linux-x64@0.33.3': '@img/sharp-linux-x64@0.33.4':
optionalDependencies: optionalDependencies:
'@img/sharp-libvips-linux-x64': 1.0.2 '@img/sharp-libvips-linux-x64': 1.0.2
optional: true optional: true
'@img/sharp-linuxmusl-arm64@0.33.3': '@img/sharp-linuxmusl-arm64@0.33.4':
optionalDependencies: optionalDependencies:
'@img/sharp-libvips-linuxmusl-arm64': 1.0.2 '@img/sharp-libvips-linuxmusl-arm64': 1.0.2
optional: true optional: true
'@img/sharp-linuxmusl-x64@0.33.3': '@img/sharp-linuxmusl-x64@0.33.4':
optionalDependencies: optionalDependencies:
'@img/sharp-libvips-linuxmusl-x64': 1.0.2 '@img/sharp-libvips-linuxmusl-x64': 1.0.2
optional: true optional: true
'@img/sharp-wasm32@0.33.3': '@img/sharp-wasm32@0.33.4':
dependencies: dependencies:
'@emnapi/runtime': 1.1.1 '@emnapi/runtime': 1.1.1
optional: true optional: true
'@img/sharp-win32-ia32@0.33.3': '@img/sharp-win32-ia32@0.33.4':
optional: true optional: true
'@img/sharp-win32-x64@0.33.3': '@img/sharp-win32-x64@0.33.4':
optional: true optional: true
'@isaacs/cliui@8.0.2': '@isaacs/cliui@8.0.2':
@ -5409,7 +5412,7 @@ snapshots:
array-uniq@1.0.3: {} array-uniq@1.0.3: {}
astro@4.8.3(@types/node@18.19.31): astro@4.8.5(@types/node@18.19.31):
dependencies: dependencies:
'@astrojs/compiler': 2.8.0 '@astrojs/compiler': 2.8.0
'@astrojs/internal-helpers': 0.4.0 '@astrojs/internal-helpers': 0.4.0
@ -5475,7 +5478,7 @@ snapshots:
zod: 3.23.8 zod: 3.23.8
zod-to-json-schema: 3.23.0(zod@3.23.8) zod-to-json-schema: 3.23.0(zod@3.23.8)
optionalDependencies: optionalDependencies:
sharp: 0.33.3 sharp: 0.33.4
transitivePeerDependencies: transitivePeerDependencies:
- '@types/node' - '@types/node'
- less - less
@ -6132,7 +6135,7 @@ snapshots:
get-stream@8.0.1: {} get-stream@8.0.1: {}
get-tsconfig@4.7.3: get-tsconfig@4.7.5:
dependencies: dependencies:
resolve-pkg-maps: 1.0.0 resolve-pkg-maps: 1.0.0
@ -7278,7 +7281,7 @@ snapshots:
dependencies: dependencies:
mimic-fn: 4.0.0 mimic-fn: 4.0.0
openai@4.45.0(encoding@0.1.13): openai@4.47.1(encoding@0.1.13):
dependencies: dependencies:
'@types/node': 18.19.31 '@types/node': 18.19.31
'@types/node-fetch': 2.6.11 '@types/node-fetch': 2.6.11
@ -7886,14 +7889,14 @@ snapshots:
setprototypeof@1.2.0: {} setprototypeof@1.2.0: {}
sharp@0.33.3: sharp@0.33.4:
dependencies: dependencies:
color: 4.2.3 color: 4.2.3
detect-libc: 2.0.3 detect-libc: 2.0.3
semver: 7.6.0 semver: 7.6.2
optionalDependencies: optionalDependencies:
'@img/sharp-darwin-arm64': 0.33.3 '@img/sharp-darwin-arm64': 0.33.4
'@img/sharp-darwin-x64': 0.33.3 '@img/sharp-darwin-x64': 0.33.4
'@img/sharp-libvips-darwin-arm64': 1.0.2 '@img/sharp-libvips-darwin-arm64': 1.0.2
'@img/sharp-libvips-darwin-x64': 1.0.2 '@img/sharp-libvips-darwin-x64': 1.0.2
'@img/sharp-libvips-linux-arm': 1.0.2 '@img/sharp-libvips-linux-arm': 1.0.2
@ -7902,15 +7905,15 @@ snapshots:
'@img/sharp-libvips-linux-x64': 1.0.2 '@img/sharp-libvips-linux-x64': 1.0.2
'@img/sharp-libvips-linuxmusl-arm64': 1.0.2 '@img/sharp-libvips-linuxmusl-arm64': 1.0.2
'@img/sharp-libvips-linuxmusl-x64': 1.0.2 '@img/sharp-libvips-linuxmusl-x64': 1.0.2
'@img/sharp-linux-arm': 0.33.3 '@img/sharp-linux-arm': 0.33.4
'@img/sharp-linux-arm64': 0.33.3 '@img/sharp-linux-arm64': 0.33.4
'@img/sharp-linux-s390x': 0.33.3 '@img/sharp-linux-s390x': 0.33.4
'@img/sharp-linux-x64': 0.33.3 '@img/sharp-linux-x64': 0.33.4
'@img/sharp-linuxmusl-arm64': 0.33.3 '@img/sharp-linuxmusl-arm64': 0.33.4
'@img/sharp-linuxmusl-x64': 0.33.3 '@img/sharp-linuxmusl-x64': 0.33.4
'@img/sharp-wasm32': 0.33.3 '@img/sharp-wasm32': 0.33.4
'@img/sharp-win32-ia32': 0.33.3 '@img/sharp-win32-ia32': 0.33.4
'@img/sharp-win32-x64': 0.33.3 '@img/sharp-win32-x64': 0.33.4
shebang-command@2.0.0: shebang-command@2.0.0:
dependencies: dependencies:
@ -8160,10 +8163,10 @@ snapshots:
tslib@2.6.2: {} tslib@2.6.2: {}
tsx@4.10.2: tsx@4.10.4:
dependencies: dependencies:
esbuild: 0.20.2 esbuild: 0.20.2
get-tsconfig: 4.7.3 get-tsconfig: 4.7.5
optionalDependencies: optionalDependencies:
fsevents: 2.3.3 fsevents: 2.3.3

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 KiB

@ -0,0 +1,75 @@
import playwright from 'playwright';
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import matter from 'gray-matter';
import type { RoadmapFrontmatter } from '../src/lib/roadmap';
// ERROR: `__dirname` is not defined in ES module scope
// https://iamwebwiz.medium.com/how-to-fix-dirname-is-not-defined-in-es-module-scope-34d94a86694d
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Usage: tsx ./scripts/editor-roadmap-dirs.ts <roadmapId>
// Directory containing the roadmaps
const ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');
const roadmapId = process.argv[2];
const allowedRoadmapIds = await fs.readdir(ROADMAP_CONTENT_DIR);
if (!roadmapId) {
console.error('Roadmap Id is required');
process.exit(1);
}
if (!allowedRoadmapIds.includes(roadmapId)) {
console.error(`Invalid roadmap key ${roadmapId}`);
console.error(`Allowed keys are ${allowedRoadmapIds.join(', ')}`);
process.exit(1);
}
const roadmapFrontmatterDir = path.join(
ROADMAP_CONTENT_DIR,
roadmapId,
`${roadmapId}.md`,
);
const roadmapFrontmatterRaw = await fs.readFile(roadmapFrontmatterDir, 'utf-8');
const { data } = matter(roadmapFrontmatterRaw);
const roadmapFrontmatter = data as RoadmapFrontmatter;
if (!roadmapFrontmatter) {
console.error('Invalid roadmap frontmatter');
process.exit(1);
}
if (roadmapFrontmatter.renderer !== 'editor') {
console.error('Only Editor Rendered Roadmaps are allowed');
process.exit(1);
}
console.log(`Launching chromium`);
const browser = await playwright.chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
const pageUrl = `http://localhost:3000/${roadmapId}/svg`;
console.log(`Opening page ${pageUrl}`);
await page.goto(pageUrl);
await page.waitForSelector('#resource-svg-wrap');
console.log(`Generating PDF ${pageUrl}`);
await page.pdf({
path: `./public/pdfs/roadmaps/${roadmapId}.pdf`,
margin: { top: 0, right: 0, bottom: 0, left: 0 },
height: roadmapFrontmatter?.dimensions?.height || 2000,
width: roadmapFrontmatter?.dimensions?.width || 968,
});
// @todo generate png from the pdf
console.log(`Generating png ${pageUrl}`);
await page.locator('#resource-svg-wrap>svg').screenshot({
path: `./public/roadmaps/${roadmapId}.png`,
type: 'png',
scale: 'device',
});
await browser.close();

@ -0,0 +1,185 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import type { Edge, Node } from 'reactflow';
import matter from 'gray-matter';
import type { RoadmapFrontmatter } from '../src/lib/roadmap';
import { slugify } from '../src/lib/slugger';
import OpenAI from 'openai';
import { runPromisesInBatchSequentially } from '../src/lib/promise';
// ERROR: `__dirname` is not defined in ES module scope
// https://iamwebwiz.medium.com/how-to-fix-dirname-is-not-defined-in-es-module-scope-34d94a86694d
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Usage: tsx ./scripts/editor-roadmap-content.ts <roadmapId>
const OPEN_AI_API_KEY = process.env.OPEN_AI_API_KEY;
console.log('OPEN_AI_API_KEY:', OPEN_AI_API_KEY);
const ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');
const roadmapId = process.argv[2];
const allowedRoadmapIds = await fs.readdir(ROADMAP_CONTENT_DIR);
if (!roadmapId) {
console.error('Roadmap Id is required');
process.exit(1);
}
if (!allowedRoadmapIds.includes(roadmapId)) {
console.error(`Invalid roadmap key ${roadmapId}`);
console.error(`Allowed keys are ${allowedRoadmapIds.join(', ')}`);
process.exit(1);
}
const roadmapFrontmatterDir = path.join(
ROADMAP_CONTENT_DIR,
roadmapId,
`${roadmapId}.md`,
);
const roadmapFrontmatterRaw = await fs.readFile(roadmapFrontmatterDir, 'utf-8');
const { data } = matter(roadmapFrontmatterRaw);
const roadmapFrontmatter = data as RoadmapFrontmatter;
if (!roadmapFrontmatter) {
console.error('Invalid roadmap frontmatter');
process.exit(1);
}
if (roadmapFrontmatter.renderer !== 'editor') {
console.error('Only Editor Rendered Roadmaps are allowed');
process.exit(1);
}
const roadmapDir = path.join(
ROADMAP_CONTENT_DIR,
roadmapId,
`${roadmapId}.json`,
);
const roadmapContent = await fs.readFile(roadmapDir, 'utf-8');
let { nodes, edges } = JSON.parse(roadmapContent) as {
nodes: Node[];
edges: Edge[];
};
const enrichedNodes = nodes
.filter(
(node) =>
node?.type &&
['topic', 'subtopic'].includes(node.type) &&
node.data?.label,
)
.map((node) => {
// Because we only need the parent id and title for subtopics
if (node.type !== 'subtopic') {
return node;
}
const parentNodeId =
edges.find((edge) => edge.target === node.id)?.source || '';
const parentNode = nodes.find((n) => n.id === parentNodeId);
return {
...node,
parentId: parentNodeId,
parentTitle: parentNode?.data?.label || '',
};
}) as (Node & { parentId?: string; parentTitle?: string })[];
const roadmapContentDir = path.join(ROADMAP_CONTENT_DIR, roadmapId, 'content');
const stats = await fs.stat(roadmapContentDir).catch(() => null);
if (!stats || !stats.isDirectory()) {
await fs.mkdir(roadmapContentDir, { recursive: true });
}
let openai: OpenAI | undefined;
if (OPEN_AI_API_KEY) {
openai = new OpenAI({
apiKey: OPEN_AI_API_KEY,
});
}
function writeTopicContent(
roadmapTitle: string,
childTopic: string,
parentTopic?: string,
) {
let prompt = `I will give you a topic and you need to write a brief introduction for that with regards to "${roadmapTitle}". Your format should be as follows and be in strictly markdown format:
# (Put a heading for the topic without adding parent "Subtopic in Topic" or "Topic in Roadmap" etc.)
(Write me a brief introduction for the topic with regards to "${roadmapTitle}")
`;
if (!parentTopic) {
prompt += `First topic is: ${childTopic}`;
} else {
prompt += `First topic is: ${childTopic} under ${parentTopic}`;
}
return new Promise((resolve, reject) => {
openai?.chat.completions
.create({
model: 'gpt-4',
messages: [
{
role: 'user',
content: prompt,
},
],
})
.then((response) => {
const article = response.choices[0].message.content;
resolve(article);
})
.catch((err) => {
reject(err);
});
});
}
async function writeNodeContent(node: Node & { parentTitle?: string }) {
const nodeDirPattern = `${slugify(node.data.label)}@${node.id}.md`;
if (!roadmapContentFiles.includes(nodeDirPattern)) {
console.log(`Missing file for: ${nodeDirPattern}`);
return;
}
const nodeDir = path.join(roadmapContentDir, nodeDirPattern);
const nodeContent = await fs.readFile(nodeDir, 'utf-8');
const isFileEmpty = !nodeContent.replace(`# ${node.data.label}`, '').trim();
if (!isFileEmpty) {
console.log(`❌ Ignoring ${nodeDirPattern}. Not empty.`);
return;
}
const topic = node.data.label;
const parentTopic = node.parentTitle;
console.log(`⏳ Generating content for ${topic}...`);
let newContentFile = '';
if (OPEN_AI_API_KEY) {
newContentFile = (await writeTopicContent(
roadmapFrontmatter.title,
topic,
parentTopic,
)) as string;
} else {
newContentFile = `# ${topic}`;
}
await fs.writeFile(nodeDir, newContentFile, 'utf-8');
console.log(`✅ Content generated for ${topic}`);
}
let roadmapContentFiles = await fs.readdir(roadmapContentDir, {
recursive: true,
});
if (!OPEN_AI_API_KEY) {
console.log('----------------------------------------');
console.log('OPEN_AI_API_KEY not found. Skipping openai api calls...');
console.log('----------------------------------------');
}
const promises = enrichedNodes.map((node) => () => writeNodeContent(node));
await runPromisesInBatchSequentially(promises, 20);
console.log('✅ All content generated');

@ -0,0 +1,86 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import type { Node } from 'reactflow';
import matter from 'gray-matter';
import type { RoadmapFrontmatter } from '../src/lib/roadmap';
import { slugify } from '../src/lib/slugger';
// ERROR: `__dirname` is not defined in ES module scope
// https://iamwebwiz.medium.com/how-to-fix-dirname-is-not-defined-in-es-module-scope-34d94a86694d
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Usage: tsx ./scripts/editor-roadmap-dirs.ts <roadmapId>
// Directory containing the roadmaps
const ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');
const roadmapId = process.argv[2];
const allowedRoadmapIds = await fs.readdir(ROADMAP_CONTENT_DIR);
if (!roadmapId) {
console.error('Roadmap Id is required');
process.exit(1);
}
if (!allowedRoadmapIds.includes(roadmapId)) {
console.error(`Invalid roadmap key ${roadmapId}`);
console.error(`Allowed keys are ${allowedRoadmapIds.join(', ')}`);
process.exit(1);
}
const roadmapFrontmatterDir = path.join(
ROADMAP_CONTENT_DIR,
roadmapId,
`${roadmapId}.md`,
);
const roadmapFrontmatterRaw = await fs.readFile(roadmapFrontmatterDir, 'utf-8');
const { data } = matter(roadmapFrontmatterRaw);
const roadmapFrontmatter = data as RoadmapFrontmatter;
if (!roadmapFrontmatter) {
console.error('Invalid roadmap frontmatter');
process.exit(1);
}
if (roadmapFrontmatter.renderer !== 'editor') {
console.error('Only Editor Rendered Roadmaps are allowed');
process.exit(1);
}
const roadmapDir = path.join(
ROADMAP_CONTENT_DIR,
roadmapId,
`${roadmapId}.json`,
);
const roadmapContent = await fs.readFile(roadmapDir, 'utf-8');
let { nodes } = JSON.parse(roadmapContent) as {
nodes: Node[];
};
nodes = nodes.filter(
(node) =>
node?.type && ['topic', 'subtopic'].includes(node.type) && node.data?.label,
);
const roadmapContentDir = path.join(ROADMAP_CONTENT_DIR, roadmapId, 'content');
const stats = await fs.stat(roadmapContentDir).catch(() => null);
if (!stats || !stats.isDirectory()) {
await fs.mkdir(roadmapContentDir, { recursive: true });
}
const roadmapContentFiles = await fs.readdir(roadmapContentDir, {
recursive: true,
});
nodes.forEach(async (node, index) => {
const nodeDirPattern = `${slugify(node.data.label)}@${node.id}.md`;
if (roadmapContentFiles.includes(nodeDirPattern)) {
console.log(`Skipping ${nodeDirPattern}`);
return;
}
await fs.writeFile(
path.join(roadmapContentDir, nodeDirPattern),
`# ${node.data.label}`,
);
});

@ -18,6 +18,7 @@ import { GuideIcon } from '../ReactIcons/GuideIcon.tsx';
import { HomeIcon } from '../ReactIcons/HomeIcon.tsx'; import { HomeIcon } from '../ReactIcons/HomeIcon.tsx';
import { VideoIcon } from '../ReactIcons/VideoIcon.tsx'; import { VideoIcon } from '../ReactIcons/VideoIcon.tsx';
import { cn } from '../../lib/classname.ts'; import { cn } from '../../lib/classname.ts';
import type { AllowedRoadmapRenderer } from '../../lib/roadmap.ts';
export type PageType = { export type PageType = {
id: string; id: string;
@ -27,6 +28,7 @@ export type PageType = {
icon?: ReactElement; icon?: ReactElement;
isProtected?: boolean; isProtected?: boolean;
metadata?: Record<string, any>; metadata?: Record<string, any>;
renderer?: AllowedRoadmapRenderer;
}; };
const defaultPages: PageType[] = [ const defaultPages: PageType[] = [

@ -24,6 +24,7 @@ export type TeamResourceConfig = {
topics?: number; topics?: number;
sharedTeamMemberIds: string[]; sharedTeamMemberIds: string[];
sharedFriendIds: string[]; sharedFriendIds: string[];
defaultRoadmapId?: string;
}[]; }[];
type RoadmapSelectorProps = { type RoadmapSelectorProps = {
@ -106,6 +107,7 @@ export function RoadmapSelector(props: RoadmapSelectorProps) {
} }
pageProgressMessage.set(`Adding roadmap to team`); pageProgressMessage.set(`Adding roadmap to team`);
const renderer = allRoadmaps.find((r) => r.id === roadmapId)?.renderer;
const { error, response } = await httpPut<TeamResourceConfig>( const { error, response } = await httpPut<TeamResourceConfig>(
`${ `${
import.meta.env.PUBLIC_API_URL import.meta.env.PUBLIC_API_URL
@ -115,6 +117,7 @@ export function RoadmapSelector(props: RoadmapSelectorProps) {
resourceId: roadmapId, resourceId: roadmapId,
resourceType: 'roadmap', resourceType: 'roadmap',
removed: [], removed: [],
renderer: renderer || 'balsamiq',
}, },
); );
@ -124,6 +127,9 @@ export function RoadmapSelector(props: RoadmapSelectorProps) {
} }
setTeamResources(response); setTeamResources(response);
if (renderer === 'editor') {
setShowSelectRoadmapModal(false);
}
} }
useEffect(() => { useEffect(() => {

@ -0,0 +1,85 @@
import { useEffect, useState, type CSSProperties } from 'react';
import {
EditorRoadmapRenderer,
type RoadmapRendererProps,
} from './EditorRoadmapRenderer';
import { Spinner } from '../ReactIcons/Spinner';
import type { ResourceType } from '../../lib/resource-progress';
import { httpGet } from '../../lib/http';
import { ProgressNudge } from '../FrameRenderer/ProgressNudge';
type EditorRoadmapProps = {
resourceId: string;
resourceType?: ResourceType;
dimensions: {
width: number;
height: number;
};
};
export function EditorRoadmap(props: EditorRoadmapProps) {
const { resourceId, resourceType = 'roadmap', dimensions } = props;
const [isLoading, setIsLoading] = useState(true);
const [roadmapData, setRoadmapData] = useState<
Omit<RoadmapRendererProps, 'resourceId'> | undefined
>(undefined);
const loadRoadmapData = async () => {
setIsLoading(true);
const { response, error } = await httpGet<
Omit<RoadmapRendererProps, 'resourceId'>
>(`/${resourceId}.json`);
if (error) {
console.error(error);
return;
}
setRoadmapData(response);
setIsLoading(false);
};
useEffect(() => {
loadRoadmapData().finally();
}, [resourceId]);
if (!roadmapData || isLoading) {
return (
<div
style={
{
'--aspect-ratio': dimensions.width / dimensions.height,
} as CSSProperties
}
className="flex aspect-[var(--aspect-ratio)] w-full justify-center"
>
<div className="flex w-full justify-center">
<Spinner
innerFill="#2563eb"
outerFill="#E5E7EB"
className="h-6 w-6 animate-spin sm:h-12 sm:w-12"
/>
</div>
</div>
);
}
return (
<div
style={
{
'--aspect-ratio': dimensions.width / dimensions.height,
} as CSSProperties
}
className="flex aspect-[var(--aspect-ratio)] w-full justify-center"
>
<EditorRoadmapRenderer
{...roadmapData}
dimensions={dimensions}
resourceId={resourceId}
/>
<ProgressNudge resourceId={resourceId} resourceType={resourceType} />
</div>
);
}

@ -0,0 +1,56 @@
svg text tspan {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeSpeed;
}
svg > g[data-type='topic'],
svg > g[data-type='subtopic'],
svg g[data-type='link-item'],
svg > g[data-type='button'] {
cursor: pointer;
}
svg > g[data-type='topic']:hover > rect {
fill: #d6d700;
}
svg > g[data-type='subtopic']:hover > rect {
fill: #f3c950;
}
svg > g[data-type='button']:hover {
opacity: 0.8;
}
svg g[data-type='link-item']:hover {
opacity: 0.8;
}
svg .done rect {
fill: #cbcbcb !important;
}
svg .done text,
svg .skipped text {
text-decoration: line-through;
}
svg > g[data-type='topic'].learning > rect + text,
svg > g[data-type='topic'].done > rect + text {
fill: black;
}
svg > g[data-type='subtipic'].done > rect + text,
svg > g[data-type='subtipic'].learning > rect + text {
fill: #cbcbcb;
}
svg .learning rect {
fill: #dad1fd !important;
}
svg .learning text {
text-decoration: underline;
}
svg .skipped rect {
fill: #496b69 !important;
}

@ -0,0 +1,176 @@
import { useCallback, useEffect, useRef } from 'react';
import './EditorRoadmapRenderer.css';
import {
renderResourceProgress,
updateResourceProgress,
type ResourceProgressType,
renderTopicProgress,
refreshProgressCounters,
} from '../../lib/resource-progress';
import { pageProgressMessage } from '../../stores/page';
import { useToast } from '../../hooks/use-toast';
import type { Edge, Node } from 'reactflow';
import { Renderer } from '../../../editor/renderer';
import { slugify } from '../../lib/slugger';
export type RoadmapRendererProps = {
resourceId: string;
nodes: Node[];
edges: Edge[];
dimensions: {
width: number;
height: number;
};
};
type RoadmapNodeDetails = {
nodeId: string;
nodeType: string;
targetGroup: SVGElement;
title?: string;
};
function getNodeDetails(svgElement: SVGElement): RoadmapNodeDetails | null {
const targetGroup = (svgElement?.closest('g') as SVGElement) || {};
const nodeId = targetGroup?.dataset?.nodeId;
const nodeType = targetGroup?.dataset?.type;
const title = targetGroup?.dataset?.title;
if (!nodeId || !nodeType) {
return null;
}
return { nodeId, nodeType, targetGroup, title };
}
const allowedNodeTypes = ['topic', 'subtopic', 'button', 'link-item'];
export function EditorRoadmapRenderer(props: RoadmapRendererProps) {
const { resourceId, nodes = [], edges = [] } = props;
const roadmapRef = useRef<HTMLDivElement>(null);
const toast = useToast();
async function updateTopicStatus(
topicId: string,
newStatus: ResourceProgressType,
) {
pageProgressMessage.set('Updating progress');
updateResourceProgress(
{
resourceId,
resourceType: 'roadmap',
topicId,
},
newStatus,
)
.then(() => {
renderTopicProgress(topicId, newStatus);
})
.catch((err) => {
toast.error('Something went wrong, please try again.');
console.error(err);
})
.finally(() => {
pageProgressMessage.set('');
refreshProgressCounters();
});
return;
}
const handleSvgClick = useCallback((e: MouseEvent) => {
const target = e.target as SVGElement;
const { nodeId, nodeType, targetGroup, title } =
getNodeDetails(target) || {};
if (!nodeId || !nodeType || !allowedNodeTypes.includes(nodeType)) {
return;
}
if (nodeType === 'button' || nodeType === 'link-item') {
const link = targetGroup?.dataset?.link || '';
const isExternalLink = link.startsWith('http');
if (isExternalLink) {
window.open(link, '_blank');
} else {
window.location.href = link;
}
return;
}
const isCurrentStatusLearning = targetGroup?.classList.contains('learning');
const isCurrentStatusSkipped = targetGroup?.classList.contains('skipped');
if (e.shiftKey) {
e.preventDefault();
updateTopicStatus(
nodeId,
isCurrentStatusLearning ? 'pending' : 'learning',
);
return;
} else if (e.altKey) {
e.preventDefault();
updateTopicStatus(nodeId, isCurrentStatusSkipped ? 'pending' : 'skipped');
return;
}
if (!title) {
return;
}
const detailsPattern = `${slugify(title)}@${nodeId}`;
window.dispatchEvent(
new CustomEvent('roadmap.node.click', {
detail: {
topicId: detailsPattern,
resourceId,
resourceType: 'roadmap',
},
}),
);
}, []);
const handleSvgRightClick = useCallback((e: MouseEvent) => {
e.preventDefault();
const target = e.target as SVGElement;
const { nodeId, nodeType, targetGroup } = getNodeDetails(target) || {};
if (!nodeId || !nodeType || !allowedNodeTypes.includes(nodeType)) {
return;
}
if (nodeType === 'button') {
return;
}
const isCurrentStatusDone = targetGroup?.classList.contains('done');
updateTopicStatus(nodeId, isCurrentStatusDone ? 'pending' : 'done');
}, []);
useEffect(() => {
if (!roadmapRef?.current) {
return;
}
roadmapRef?.current?.addEventListener('click', handleSvgClick);
roadmapRef?.current?.addEventListener('contextmenu', handleSvgRightClick);
return () => {
roadmapRef?.current?.removeEventListener('click', handleSvgClick);
roadmapRef?.current?.removeEventListener(
'contextmenu',
handleSvgRightClick,
);
};
}, []);
return (
<Renderer
ref={roadmapRef}
roadmap={{ nodes, edges }}
onRendered={() => {
roadmapRef.current?.setAttribute('data-renderer', 'editor');
renderResourceProgress('roadmap', resourceId).finally();
}}
/>
);
}

@ -52,7 +52,7 @@ svg .done rect {
fill: #cbcbcb !important; fill: #cbcbcb !important;
} }
svg .done rect[stroke="rgb(255,229,153)"] { svg .done rect[stroke='rgb(255,229,153)'] {
stroke: #cbcbcb !important; stroke: #cbcbcb !important;
} }
@ -133,10 +133,12 @@ svg .removed path {
} }
} }
#customized-roadmap #resource-svg-wrap g:not([class]), #customized-roadmap #resource-svg-wrap:not([data-renderer]) g:not([class]),
#customized-roadmap #resource-svg-wrap circle, #customized-roadmap #resource-svg-wrap:not([data-renderer]) circle,
#customized-roadmap #resource-svg-wrap path[stroke='#fff'], #customized-roadmap #resource-svg-wrap:not([data-renderer]) path[stroke='#fff'],
#customized-roadmap #resource-svg-wrap g[data-group-id$='-note'] { #customized-roadmap
#resource-svg-wrap:not([data-renderer])
g[data-group-id$='-note'] {
display: none; display: none;
} }

@ -7,12 +7,14 @@ import { useToast } from '../../hooks/use-toast';
import { TrashIcon } from '../ReactIcons/TrashIcon'; import { TrashIcon } from '../ReactIcons/TrashIcon';
import { AddedUserIcon } from '../ReactIcons/AddedUserIcon'; import { AddedUserIcon } from '../ReactIcons/AddedUserIcon';
import { AddUserIcon } from '../ReactIcons/AddUserIcon'; import { AddUserIcon } from '../ReactIcons/AddUserIcon';
import type { AllowedRoadmapRenderer } from '../../lib/roadmap';
type FriendProgressItemProps = { type FriendProgressItemProps = {
friend: ListFriendsResponse[0]; friend: ListFriendsResponse[0];
onShowResourceProgress: ( onShowResourceProgress: (
resourceId: string, resourceId: string,
isCustomResource?: boolean isCustomResource?: boolean,
renderer?: AllowedRoadmapRenderer,
) => void; ) => void;
onReload: () => void; onReload: () => void;
}; };
@ -27,7 +29,7 @@ export function FriendProgressItem(props: FriendProgressItemProps) {
pageProgressMessage.set('Please wait...'); pageProgressMessage.set('Please wait...');
const { response, error } = await httpDelete( const { response, error } = await httpDelete(
`${import.meta.env.PUBLIC_API_URL}/v1-delete-friend/${userId}`, `${import.meta.env.PUBLIC_API_URL}/v1-delete-friend/${userId}`,
{} {},
); );
if (error || !response) { if (error || !response) {
@ -43,7 +45,7 @@ export function FriendProgressItem(props: FriendProgressItemProps) {
pageProgressMessage.set('Please wait...'); pageProgressMessage.set('Please wait...');
const { response, error } = await httpPost( const { response, error } = await httpPost(
`${import.meta.env.PUBLIC_API_URL}/v1-add-friend/${userId}`, `${import.meta.env.PUBLIC_API_URL}/v1-add-friend/${userId}`,
{} {},
); );
if (error || !response) { if (error || !response) {
@ -92,7 +94,8 @@ export function FriendProgressItem(props: FriendProgressItemProps) {
onClick={() => onClick={() =>
onShowResourceProgress( onShowResourceProgress(
progress.resourceId, progress.resourceId,
progress.isCustomResource progress.isCustomResource,
progress?.renderer,
) )
} }
className="group relative overflow-hidden rounded-md border p-2 hover:border-gray-300 hover:text-black focus:outline-none" className="group relative overflow-hidden rounded-md border p-2 hover:border-gray-300 hover:text-black focus:outline-none"
@ -160,7 +163,7 @@ export function FriendProgressItem(props: FriendProgressItemProps) {
deleteFriend(friend.userId, 'Friend removed').finally( deleteFriend(friend.userId, 'Friend removed').finally(
() => { () => {
pageProgressMessage.set(''); pageProgressMessage.set('');
} },
); );
}} }}
> >
@ -198,7 +201,7 @@ export function FriendProgressItem(props: FriendProgressItemProps) {
addFriend(friend.userId, 'Friend request accepted').finally( addFriend(friend.userId, 'Friend request accepted').finally(
() => { () => {
pageProgressMessage.set(''); pageProgressMessage.set('');
} },
); );
}} }}
> >
@ -225,7 +228,7 @@ export function FriendProgressItem(props: FriendProgressItemProps) {
deleteFriend(friend.userId, 'Friend request removed').finally( deleteFriend(friend.userId, 'Friend request removed').finally(
() => { () => {
pageProgressMessage.set(''); pageProgressMessage.set('');
} },
); );
}} }}
> >
@ -267,7 +270,7 @@ export function FriendProgressItem(props: FriendProgressItemProps) {
onClick={() => { onClick={() => {
deleteFriend( deleteFriend(
friend.userId, friend.userId,
'Friend request withdrawn' 'Friend request withdrawn',
).finally(() => { ).finally(() => {
pageProgressMessage.set(''); pageProgressMessage.set('');
}); });
@ -304,7 +307,7 @@ export function FriendProgressItem(props: FriendProgressItemProps) {
addFriend(friend.userId, 'Friend request accepted').finally( addFriend(friend.userId, 'Friend request accepted').finally(
() => { () => {
pageProgressMessage.set(''); pageProgressMessage.set('');
} },
); );
}} }}
className="mb-1 block w-full max-w-[150px] rounded-md bg-black py-1.5 text-sm text-white" className="mb-1 block w-full max-w-[150px] rounded-md bg-black py-1.5 text-sm text-white"
@ -316,7 +319,7 @@ export function FriendProgressItem(props: FriendProgressItemProps) {
onClick={() => { onClick={() => {
deleteFriend( deleteFriend(
friend.userId, friend.userId,
'Friend request rejected' 'Friend request rejected',
).finally(() => { ).finally(() => {
pageProgressMessage.set(''); pageProgressMessage.set('');
}); });

@ -11,6 +11,7 @@ import { UserProgressModal } from '../UserProgress/UserProgressModal';
import { InviteFriendPopup } from './InviteFriendPopup'; import { InviteFriendPopup } from './InviteFriendPopup';
import { UserCustomProgressModal } from '../UserProgress/UserCustomProgressModal'; import { UserCustomProgressModal } from '../UserProgress/UserCustomProgressModal';
import { UserIcon } from 'lucide-react'; import { UserIcon } from 'lucide-react';
import type { AllowedRoadmapRenderer } from '../../lib/roadmap';
type FriendResourceProgress = { type FriendResourceProgress = {
updatedAt: string; updatedAt: string;
@ -22,6 +23,7 @@ type FriendResourceProgress = {
skipped: number; skipped: number;
done: number; done: number;
total: number; total: number;
renderer?: AllowedRoadmapRenderer;
}; };
export type ListFriendsResponse = { export type ListFriendsResponse = {
@ -55,6 +57,7 @@ export function FriendsPage() {
resourceId: string; resourceId: string;
friend: ListFriendsResponse[0]; friend: ListFriendsResponse[0];
isCustomResource?: boolean; isCustomResource?: boolean;
renderer?: AllowedRoadmapRenderer;
}>(); }>();
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
@ -92,8 +95,8 @@ export function FriendsPage() {
(grouping) => grouping.value === selectedGrouping, (grouping) => grouping.value === selectedGrouping,
); );
const filteredFriends = friends.filter( const filteredFriends = friends.filter((friend) =>
(friend) => selectedGroupingType?.statuses.includes(friend.status), selectedGroupingType?.statuses.includes(friend.status),
); );
const receivedRequests = friends.filter( const receivedRequests = friends.filter(
@ -124,6 +127,7 @@ export function FriendsPage() {
resourceType={'roadmap'} resourceType={'roadmap'}
onClose={() => setShowFriendProgress(undefined)} onClose={() => setShowFriendProgress(undefined)}
isCustomResource={showFriendProgress?.isCustomResource} isCustomResource={showFriendProgress?.isCustomResource}
renderer={showFriendProgress?.renderer}
/> />
); );
@ -182,11 +186,16 @@ export function FriendsPage() {
{filteredFriends.map((friend) => ( {filteredFriends.map((friend) => (
<FriendProgressItem <FriendProgressItem
friend={friend} friend={friend}
onShowResourceProgress={(resourceId, isCustomResource) => { onShowResourceProgress={(
resourceId,
isCustomResource,
renderer,
) => {
setShowFriendProgress({ setShowFriendProgress({
resourceId, resourceId,
friend, friend,
isCustomResource, isCustomResource,
renderer,
}); });
}} }}
key={friend.userId} key={friend.userId}

@ -1,6 +1,6 @@
--- ---
import { getQuestionGroupsByIds } from '../lib/question-group'; import { getQuestionGroupsByIds } from '../lib/question-group';
import { getRoadmapsByIds, RoadmapFrontmatter } from '../lib/roadmap'; import { getRoadmapsByIds, type RoadmapFrontmatter } from '../lib/roadmap';
import { Map, Clipboard } from 'lucide-react'; import { Map, Clipboard } from 'lucide-react';
export interface Props { export interface Props {
@ -59,14 +59,19 @@ const relatedQuestionDetails = await getQuestionGroupsByIds(relatedQuestions);
{ {
relatedRoadmaps.length && ( relatedRoadmaps.length && (
<div class:list={['border-t bg-gray-100', { <div
'mt-8': !relatedQuestionDetails.length class:list={[
}]}> 'border-t bg-gray-100',
{
'mt-8': !relatedQuestionDetails.length,
},
]}
>
<div class='container'> <div class='container'>
<div class='relative -top-5 flex justify-between'> <div class='relative -top-5 flex justify-between'>
<span class='text-md flex items-center rounded-md border bg-white px-3 py-1 font-medium'> <span class='text-md flex items-center rounded-md border bg-white px-3 py-1 font-medium'>
<Map className='text-black mr-1.5' size='17px' /> <Map className='text-black mr-1.5' size='17px' />
Related <span class="hidden sm:inline">Roadmaps</span> Related <span class='hidden sm:inline'>Roadmaps</span>
</span> </span>
<a <a
href='/roadmaps' href='/roadmaps'

@ -23,7 +23,7 @@ const hasTnsBanner = !!tnsBannerLink;
<div <div
class:list={[ class:list={[
'mt-4 sm:mt-7 border-0 sm:border rounded-md mb-0 bg-white', 'mb-0 mt-4 rounded-md border-0 bg-white sm:mt-7 sm:border',
...(hasTnsBanner ...(hasTnsBanner
? [ ? [
{ {
@ -42,7 +42,7 @@ const hasTnsBanner = !!tnsBannerLink;
<ResourceProgressStats <ResourceProgressStats
resourceId={roadmapId} resourceId={roadmapId}
resourceType='roadmap' resourceType='roadmap'
hasSecondaryBanner={hasTitleQuestion} hasSecondaryBanner={Boolean(hasTitleQuestion)}
/> />
{ {

@ -77,6 +77,12 @@ const groups: GroupType[] = [
type: 'role', type: 'role',
otherGroups: ['Web Development', 'Absolute Beginners'], otherGroups: ['Web Development', 'Absolute Beginners'],
}, },
{
title: 'API Design',
link: '/api',
type: 'role',
otherGroups: ['Web Development'],
},
{ {
title: 'QA', title: 'QA',
link: '/qa', link: '/qa',

@ -189,10 +189,10 @@ export function TeamActivityPage() {
Team Activity Team Activity
</h3> </h3>
<ul className="mb-4 mt-2 flex flex-col gap-3"> <ul className="mb-4 mt-2 flex flex-col gap-3">
{usersWithActivities.map((user) => { {usersWithActivities.map((user, index) => {
return ( return (
<TeamActivityItem <TeamActivityItem
key={user._id} key={`${user._id}-${index}`}
user={user} user={user}
teamId={teamId} teamId={teamId}
onTopicClick={setSelectedActivity} onTopicClick={setSelectedActivity}

@ -15,6 +15,7 @@ import type { ResourceType } from '../../lib/resource-progress';
import { MemberProgressModal } from '../TeamProgress/MemberProgressModal'; import { MemberProgressModal } from '../TeamProgress/MemberProgressModal';
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { $currentTeam } from '../../stores/team'; import { $currentTeam } from '../../stores/team';
import { MemberCustomProgressModal } from '../TeamProgress/MemberCustomProgressModal';
type GetTeamMemberProgressesResponse = TeamMemberDocument & { type GetTeamMemberProgressesResponse = TeamMemberDocument & {
name: string; name: string;
@ -99,10 +100,15 @@ export function TeamMemberDetailsPage() {
? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${memberProgress?.avatar}` ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${memberProgress?.avatar}`
: '/images/default-avatar.png'; : '/images/default-avatar.png';
const ProgressModal =
selectedResource && !selectedResource.isCustomResource
? MemberProgressModal
: MemberCustomProgressModal;
return ( return (
<> <>
{selectedResource && ( {selectedResource && (
<MemberProgressModal <ProgressModal
teamId={teamId} teamId={teamId}
member={{ member={{
...memberProgress, ...memberProgress,
@ -183,7 +189,11 @@ export function TeamMemberDetailsPage() {
memberActivity?.data?.flatMap((act) => act.activity) || [] memberActivity?.data?.flatMap((act) => act.activity) || []
} }
onResourceClick={(resourceId, resourceType, isCustomResource) => { onResourceClick={(resourceId, resourceType, isCustomResource) => {
setSelectedResource({ resourceId, resourceType, isCustomResource }); setSelectedResource({
resourceId,
resourceType,
isCustomResource,
});
}} }}
/> />
<Pagination <Pagination

@ -147,6 +147,7 @@ export function TeamRoadmaps() {
toast.loading('Adding roadmap'); toast.loading('Adding roadmap');
pageProgressMessage.set('Adding roadmap'); pageProgressMessage.set('Adding roadmap');
setIsLoading(true); setIsLoading(true);
const roadmap = allRoadmaps.find((r) => r.id === roadmapId);
const { error, response } = await httpPut<TeamResourceConfig>( const { error, response } = await httpPut<TeamResourceConfig>(
`${ `${
import.meta.env.PUBLIC_API_URL import.meta.env.PUBLIC_API_URL
@ -156,6 +157,7 @@ export function TeamRoadmaps() {
resourceId: roadmapId, resourceId: roadmapId,
resourceType: 'roadmap', resourceType: 'roadmap',
removed: [], removed: [],
renderer: roadmap?.renderer || 'balsamiq',
}, },
); );
@ -166,6 +168,9 @@ export function TeamRoadmaps() {
setTeamResources(response); setTeamResources(response);
toast.success('Roadmap added'); toast.success('Roadmap added');
if (roadmap?.renderer === 'editor') {
setIsAddingRoadmap(false);
}
} }
async function onRemove(resourceId: string) { async function onRemove(resourceId: string) {
@ -219,11 +224,14 @@ export function TeamRoadmaps() {
/> />
); );
const filteredAllRoadmaps = allRoadmaps.filter(
(r) => !teamResources.find((c) => c?.defaultRoadmapId === r.id),
);
const addRoadmapModal = isAddingRoadmap && ( const addRoadmapModal = isAddingRoadmap && (
<SelectRoadmapModal <SelectRoadmapModal
onClose={() => setIsAddingRoadmap(false)} onClose={() => setIsAddingRoadmap(false)}
teamResourceConfig={teamResources} teamResourceConfig={teamResources}
allRoadmaps={allRoadmaps} allRoadmaps={filteredAllRoadmaps}
teamId={teamId} teamId={teamId}
onRoadmapAdd={(roadmapId: string) => { onRoadmapAdd={(roadmapId: string) => {
onAdd(roadmapId).finally(() => { onAdd(roadmapId).finally(() => {

@ -106,6 +106,10 @@ export function TeamVersions(props: TeamVersionsProps) {
}, []); }, []);
useEffect(() => { useEffect(() => {
if (!selectedTeamVersion) {
return;
}
clearResourceProgress(); clearResourceProgress();
// teams have customizations. Assigning #customized-roadmap to roadmapSvgWrap // teams have customizations. Assigning #customized-roadmap to roadmapSvgWrap

@ -225,11 +225,12 @@ export function TopicDetail(props: TopicDetailProps) {
className="fixed right-0 top-0 z-40 flex h-screen w-full flex-col overflow-y-auto bg-white p-4 focus:outline-0 sm:max-w-[600px] sm:p-6" className="fixed right-0 top-0 z-40 flex h-screen w-full flex-col overflow-y-auto bg-white p-4 focus:outline-0 sm:max-w-[600px] sm:p-6"
> >
{isLoading && ( {isLoading && (
<div className="flex w-full justify-center"> <div className="flex w-full h-full items-center justify-center">
<Spinner <Spinner
outerFill="#d1d5db" outerFill="#d1d5db"
className="h-6 w-6 sm:h-12 sm:w-12" className="h-6 w-6 sm:h-8 sm:w-8"
innerFill="#2563eb" innerFill="#2563eb"
isDualRing={false}
/> />
</div> </div>
)} )}

@ -11,6 +11,9 @@ import { useAuth } from '../../hooks/use-auth';
import { ModalLoader } from './ModalLoader.tsx'; import { ModalLoader } from './ModalLoader.tsx';
import { UserProgressModalHeader } from './UserProgressModalHeader'; import { UserProgressModalHeader } from './UserProgressModalHeader';
import { X } from 'lucide-react'; import { X } from 'lucide-react';
import type { PageType } from '../CommandMenu/CommandMenu.tsx';
import type { AllowedRoadmapRenderer } from '../../lib/roadmap.ts';
import { renderFlowJSON } from '../../../editor/renderer/renderer.ts';
export type ProgressMapProps = { export type ProgressMapProps = {
userId?: string; userId?: string;
@ -18,6 +21,7 @@ export type ProgressMapProps = {
resourceType: ResourceType; resourceType: ResourceType;
onClose?: () => void; onClose?: () => void;
isCustomResource?: boolean; isCustomResource?: boolean;
renderer?: AllowedRoadmapRenderer;
}; };
export type UserProgressResponse = { export type UserProgressResponse = {
@ -39,6 +43,7 @@ export function UserProgressModal(props: ProgressMapProps) {
resourceType, resourceType,
userId: propUserId, userId: propUserId,
onClose: onModalClose, onClose: onModalClose,
renderer = 'balsamiq',
} = props; } = props;
const { s: userId = propUserId } = getUrlParams(); const { s: userId = propUserId } = getUrlParams();
@ -87,15 +92,18 @@ export function UserProgressModal(props: ProgressMapProps) {
async function getRoadmapSVG( async function getRoadmapSVG(
jsonUrl: string, jsonUrl: string,
renderer: AllowedRoadmapRenderer = 'balsamiq',
): Promise<SVGElement | undefined> { ): Promise<SVGElement | undefined> {
const { error, response: roadmapJson } = await httpGet(jsonUrl); const { error, response: roadmapJson } = await httpGet(jsonUrl);
if (error || !roadmapJson) { if (error || !roadmapJson) {
throw error || new Error('Something went wrong. Please try again!'); throw error || new Error('Something went wrong. Please try again!');
} }
return await wireframeJSONToSVG(roadmapJson, { return renderer === 'editor'
fontURL: '/fonts/balsamiq.woff2', ? await renderFlowJSON(roadmapJson as any)
}); : await wireframeJSONToSVG(roadmapJson, {
fontURL: '/fonts/balsamiq.woff2',
});
} }
function onClose() { function onClose() {
@ -124,8 +132,10 @@ export function UserProgressModal(props: ProgressMapProps) {
} }
setIsLoading(true); setIsLoading(true);
setError('');
Promise.all([ Promise.all([
getRoadmapSVG(resourceJsonUrl), getRoadmapSVG(resourceJsonUrl, renderer),
getUserProgress(userId, resourceType, resourceId), getUserProgress(userId, resourceType, resourceId),
]) ])
.then(([svg, user]) => { .then(([svg, user]) => {

File diff suppressed because one or more lines are too long

@ -0,0 +1,63 @@
---
jsonUrl: '/jsons/roadmaps/api.json'
pdfUrl: '/pdfs/roadmaps/api.pdf'
order: 9
isForkable: false
briefTitle: 'API Design'
briefDescription: 'Step by step guide to learn how to design and build robust APIs.'
title: 'API Design'
description: 'Step by step guide to learn how to design and build robust APIs.'
isNew: true
hasTopics: true
dimensions:
width: 968
height: 2317.91
schema:
headline: 'API Design'
description: 'Step by step guide to learn how to design and build robust APIs.'
imageUrl: 'https://roadmap.sh/roadmaps/api.png'
datePublished: '2023-05-17'
dateModified: '2023-05-17'
seo:
title: 'API Design'
description: 'Step by step guide to learn how to design and build robust APIs in 2024.'
keywords:
- 'guide to becoming a api designer'
- 'guide to becoming an api engineer'
- 'api developer'
- 'api engineer'
- 'api skills'
- 'guide to api'
- 'asp.net developer roadmap'
- 'asp net developer roadmap'
- 'asp developer roadmap'
- 'api roadmap'
- 'api skills'
- 'api skills test'
- 'skills for api'
- 'cloud development'
- 'what is api'
- 'api quiz'
- 'api interview questions'
- 'api engineer roadmap'
- 'api developer roadmap'
- 'become an api developer'
- 'api developer career path'
- 'api developer'
- 'modern api developer'
relatedRoadmaps:
- 'backend'
- 'devops'
- 'python'
- 'golang'
- 'java'
- 'nodejs'
sitemap:
priority: 1
changefreq: 'monthly'
tags:
- 'roadmap'
- 'main-sitemap'
- 'skill-roadmap'
renderer: 'editor'
---

@ -0,0 +1,3 @@
# API Documentation Tools
API Documentation Tools are instrumental in conveying the intricacies of API design to both technical developers and non-technical stakeholders. These tools help in creating comprehensive, easy-to-understand, and searchable documentation encompassing all the elements of an API such as its functions, classes, return types, arguments, and more. Thorough documentation is central in API design as it fosters seamless adoption, effective implementation, and efficient troubleshooting of APIs. Various tools exist including Swagger, DapperDox, and ReDoc, each with unique functionalities to suit different API documentation requirements.

@ -0,0 +1,3 @@
# API Gateways
API Gateways act as the main point of entry in a microservices architecture, often responsible for request routing, composition, and protocol translation. They play a significant role in API design by providing a shared layer to handle non-business tasks. This not only simplifies how consumers interact with the backend services but also helps in maintaining the security, enforcing policies, and providing analytics over the API usage. When designing APIs, understanding and implementing efficient API Gateways is an invaluable skill, as these gateways form a crucial component of any well-structured, scalable API architecture.

@ -0,0 +1,3 @@
# API Integration Patterns
API Integration Patterns, in the context of API Design, refers to the common paradigms and approaches used to enable communication between services. These patterns dictate how different APIs interact and exchange data, allowing software applications to work cohesively. They play a vital role in application development by providing a standard method for connecting diverse software components. By understanding and implementing these patterns, developers can design more robust, scalable, and interoperable APIs.

@ -0,0 +1,3 @@
# API Keys & Management
API keys and management is an integral part of API design. An API key is a unique identifier used to authenticate a user, developer, or calling program to an API. This ensures security and control over API endpoints, as only those with a valid API key can make requests. API Management, on the other hand, refers to the practices and tools that enable an organization to govern and monitor its API usage. It involves all the aspects of managing APIs including design, deployment, documentation, security, versioning, and analytics. Both elements play crucial roles in securing and organizing API access for efficient and controlled data sharing and communication.

@ -0,0 +1,3 @@
# API Lifecycle Management
API Lifecycle Management is a crucial aspect in API design that oversees the process of creating, managing, and retiring APIs. This involves various stages from initial planning, designing, testing, deployment, to eventual retirement of the API. Proper lifecycle management ensures that an API meets the requirements, is reliable, and that it evolves with the needs of end users and developers. Moreover, it helps in maintaining the security, performance, and accessibility of the API throughout its lifetime. This comprehensive approach enables organizations to make the most of their APIs, mitigate issues, and facilitate successful digital transformation.

@ -0,0 +1,3 @@
# API Performance
When we talk about API design, one crucial aspect that demands our attention is API Performance. API Performance refers to the efficiency and speed at which a developed API can execute tasks and communicate with other programs or software components. This fundamental aspect can directly impact the responsiveness of an application, determining how quickly data can be exchanged, processed, and presented to the end-user. Improving the API performance often resolves problems related to the user experience and enhances the overall performance of the application that the API is integrated with. API performance, therefore, plays a pivotal role both in facilitating optimized interactions between systems and in determining the overall success of the digital products that rely on such interfaces.

@ -0,0 +1,3 @@
# API Security
API Security refers to the practices and products that are used to secure application programming interfaces (APIs). In the context of design, it is an essential component that helps ensure that a deployed API achieves its objectives in a safe and secure manner. This includes safeguarding the data, preventing unauthorized access, and protecting the system that hosts the API. API security encompasses the strategies, procedures and technology used to protect APIs from malicious attacks or unauthorized access while guaranteeing optimum performance, availability, and data privacy.

@ -0,0 +1,3 @@
# API Testing
API Testing refers to the process of checking the functionality, reliability, performance, and security of Application Programming Interfaces (APIs). It plays a crucial role in API design as it ensures that the APIs work correctly and as expected. This kind of testing does not require a user interface and mainly focuses on the business logic layer of the software architecture. API Testing is integral to guarantee that the data communication and responses between different software systems are error-free and streamlined.

@ -0,0 +1,3 @@
# Attribute Based Access Control (ABAC) - An Authorization Method in API Design
Attribute Based Access Control (ABAC) is a flexible and powerful authorization method in the realm of API Design. Distinct from Role-Based Access Control (RBAC), which relies on predefined roles and permissions, ABAC uses attributes to build policies and make decisions. These attributes can be associated with the user, the action they want to perform, targeted resources, or the environment. With ABAC, finer-grained access control can be achieved, thereby improving the security and efficiency of APIs. This approach is widely used in complex and dynamic environments where access control requirements can be multifaceted and deeply context-dependent.

@ -0,0 +1,3 @@
# Authentication Methods in API Design
Application Programming Interfaces (APIs) are critical components in software development that allow different software systems to communicate and share functionality. To ensure secure communication, it's essential to authenticate the parties involved in the API transactions. The authentication process confirms the identity of the API user. There are numerous authentication methods available when designing an API, each with its own pros and cons. This includes Basic Authentication, API Key Authentication, OAuth, and JWT among others. Understanding these different methods and their best use cases is fundamental to designing secure and effective APIs.

@ -0,0 +1,3 @@
# Authorization Methods in API Design
In API design, authorization methods play a crucial role in ensuring the security and integrity of data transactions. They are the mechanisms through which an API identifies and validates a user, system, or application before granting them access to specific resources. These methods include Basic Authentication, OAuth, Token-based authentication, JSON Web Tokens (JWT), and API Key based, among others. So, understanding these methods enhances the ability to design APIs that effectively protect resources while allowing necessary access. Each method has its own pros and cons, usage scenarios and security features that make them more suitable for certain situations rather than others.

@ -0,0 +1,3 @@
# Basic Auth in API Design
Basic Auth, short for Basic Authentication, is a simple method often used in API design for handling user authentication. In this method, client credentials, consisting of a username and password pair, are passed to the API server in a field in the HTTP header. The server then verifies these credentials before granting access to protected resources. Although Basic Auth is straightforward to implement, it is less secure compared to more advanced methods since it involves transmitting credentials in an encoded, but not encrypted, format. It is often used in cases where simplicity is paramount, or High security levels are not required.

@ -0,0 +1,3 @@
# Basics of DNS
When discussing the foundational elements of API Design, the Basics of DNS (Domain Name System) can't be overlooked. DNS plays a fundamental role in the way APIs function, acting as the internet's equivalent of a phone book, it interprets human-friendly hostnames into IP addresses that APIs need for communication. Understanding this complex system is essential as it allows for better comprehension of the navigation and messaging flow in API Design. For API developers, knowledge about DNS can significantly aid in troubleshooting connectivity issues, ensuring secure connections, and optimizing API architecture with more efficient calls.

@ -0,0 +1,3 @@
# Batch Processing in API Design
Batch Processing refers to the method of handling bulk data requests in API design. Here, multiple API requests are packed and processed as a single group or 'batch'. Instead of making numerous individual API calls, a user can make one batch request with numerous operations. This approach can increase performance and efficiency by reducing the overhead of establishing and closing multiple connections. The concept of 'batch processing' in API design is particularly useful in data-intensive applications or systems where the need for processing high volumes of data is prevalent.

@ -0,0 +1,3 @@
# Best Practices in API Design
API design has rapidly emerged as a vital component of software development. When designing an API, it is crucial to follow best practices to ensure optimization, scalability, and efficiency. The best practices in API design revolve around principles such as simplicity, consistency, security, and proper documentation among others. These practices not only smoothens the development process but also makes the API more user-friendly, stable, and easily maintainable. Thus, following the best practices in API design is not an option but rather a must for developers and organizations looking to create APIs that last longer and perform better.

@ -0,0 +1,3 @@
# Building JSON / RESTful APIs
Building JSON/RESTful APIs involves designing and implementing APIs that adhere to the architectural constraints of Representational State Transfer (REST). These APIs use JSON (JavaScript Object Notation) as a format for information interchange, due to its lightweight, easy-to-understand, and universally accepted nature. A well-designed RESTful API, utilizing JSON, is key in developing applications that are scalable, maintainable, and easily integrated with other systems. This design approach enables the resources on a server to be accessed and manipulated using standard HTTP protocols, facilitating communication between different services and systems. Furthermore, it enables client-server interactions to be stateless, meaning each request from a client must contain all the information needed by the server to understand and process the request.

@ -0,0 +1,3 @@
# Caching Strategies in API Design
Caching in API design serves as a technique that allows you to store copies of data temporarily in places where you can access it more readily. By obtaining this data from high-speed storage rather than slower storage sources, you can help improve the overall speed and performance of the API. Multiple strategies such as HTTP caching, database caching, application caching, and CDN caching can be implemented, each with its own sets of advantages and considerations. Understanding different caching strategies in the context of API design is crucial for designing efficient, high-performing APIs.

@ -0,0 +1,3 @@
# CCPA under Standards and Compliance in API Design
The California Consumer Privacy Act (CCPA) is a pivotal state statute meant to enhance privacy rights and consumer protection for individuals within California, United States. API Design greatly impacts compliance with CCPA, as improper management and exposure of user data can potentially violate this law. Crucially, designing APIs means considering data privacy, security, and user consent from the very foundation. Programmatically, CCPA compliance may involve structuring APIs to respond to user demands such as data access, data deletion, and opt-out requests. It imposes a significant responsibility on API developers to enforce user control over data and maintain rigorous standards of data protection.

@ -0,0 +1,3 @@
# Common Vulnerabilities in API Design
API design is a critical component of modern software development, enabling various applications to communicate and share data. However, as the use of APIs expands, so does the potential for security vulnerabilities. Understanding common vulnerabilities in API design is crucial to protecting sensitive data and maintaining a secure system. These vulnerabilities might arise due to lack of proper validation, weak authentication mechanisms, insecure endpoint configurations among others. This topic will delve into these common vulnerabilities, focusing on their identification, potential impacts, and how to design APIs with security best practices to mitigate these threats.

@ -0,0 +1,3 @@
# Content Negotiation in API Design
In the context of API design, Content Negotiation refers to the process where the client and the server communicate about the data representation which is acceptable for both of them. It allows clients to indicate the preferred response format, such as JSON, XML, or HTML. This mechanism leads to flexible and adaptable APIs, enhancing their usability. Understanding and efficiently utilizing content negotiation is an integral part of mastering API design basics.

@ -0,0 +1,3 @@
# Contract Testing in API Design
Contract Testing is a critical aspect of maintaining a robust and reliable API infrastructure. In the realm of API design, Contract Testing refers to the method of ensuring that APIs work as anticipated and that changes to them do not break their intended functionality. This approach validates the interaction between two different systems, typically consumer and provider ( API), ensuring they comply with their agreed-upon contract. By defining clear and concise contracts for our APIs, developers can avoid common deployment issues and enhance system integration processes.

@ -0,0 +1,3 @@
# Cookies in API Design
Cookies play an instrumental role in the field of API (Application Programming Interface) design. Essentially, cookies are small bits of data stored on a user's browser that enables stateful HTTP sessions, by storing pertinent information between server communications. In API design, cookies are especially useful when authentication is required. Cookies can store session tokens, thereby allowing users to stay logged in across multiple sessions or different web pages. Understanding cookies and how they function is vital in API design for sustaining user sessions, providing enhanced user experience, and securing user information.

@ -0,0 +1,3 @@
# CORS under API Design
Cross-Origin Resource Sharing (CORS) is a critical concept in API Design. It is a mechanism that uses HTTP headers to tell browsers to give a web application running at one origin, access to selected resources from a different origin. By default, web browsers prohibit web pages from making requests to a different domain than the one the web page came from. CORS is the guideline that lets you configure a set of rules on the server to define which types of cross-domain requests are allowed, providing much-needed flexibility without compromising security. Understanding CORS is crucial in designing APIs that ensure safe and effective inter-domain communication.

@ -0,0 +1,3 @@
# Different API Styles
Application Programming Interface (API) design isn't a one-size-fits-all endeavor. APIs can be structured in various styles, each with its own unique characteristics, advantages, and use cases. Early identification of the appropriate API style is crucial in ensuring a functional, efficient and seamless end-user experience. Commonly used API styles include REST, SOAP, GraphQL, and gRPC. Understanding these diverse API styles would help in making better design choices, fostering efficient overall system architecture, and promoting an intuitive and easy-to-use application.

@ -0,0 +1,5 @@
# Error Handling / Retries
When creating effective API designs, addressing Error Handling and Retries forms an essential facet. This is primarily due to the fact that APIs aren't always error-free and instances of network hiccups or input inaccuracies from users can occur. Without robust error handling, such occurrences can easily lead to catastrophic application failure or unsatisfactory user experiences.
In this context, error handling can refer to validating inputs, managing exceptions, and returning appropriate error message or status codes to the user. Meanwhile, the concept of retries comes into play to ensure maximum request success amidst transient failures. Through correctly implemented retries, an API can repeatedly attempt to execute a request until it is successful, thus ensuring seamless operation. The criteria and mechanisms of retries, including the count, delay, and conditions for retries, are crucial aspects to solidify during the API design.

@ -0,0 +1,3 @@
# Error Handling in API Design
Error Handling is a crucial aspect of API design that ensures the stability, usability, and reliability of the API in production. APIs are designed to help systems communicate with each other. However, there can be instances where these systems might encounter exceptions or errors. The process of predicting, catching, and managing these error occurrences is what we refer to as 'Error Handling'. In the context of API Design, it involves defining and implementing specific strategies to detect, manage and inform consumers of any exception or error that occurs while executing requests. Configuring this appropriately provides a more robust and seamless communication experience, enabling developers to debug and rectify issues more efficiently.

@ -0,0 +1,3 @@
# Event Driven Architecture in API Design
Event-driven architecture (EDA) is a software design concept that revolves around the production, interpretation, and consumption of events. With regards to API design, EDA grants systems the flexibility to decentralize analytics, microservices, and operations, thus promoting real-time information sharing and reaction. Event-driven APIs prioritize asynchronous communication, allowing applications to stay responsive even when tackling heavy data loads. For an effective API, adhering to EDA provides data reliability, maturity with a scalable structure, and efficient real-time data processing capabilities.

@ -0,0 +1,3 @@
# Functional Testing in API Design
Functional testing in the context of API design involves validating the endpoints and key-value pairs of an API. It ensures the server response works as expected and assesses the functionality of the API -- whether it is performing all the intended functions correctly. Various approaches like testing request-response pairs, error codes, and data accuracy are used. Functional testing can provide invaluable insights into how well an API meets the specified requirements and whether it is ready for integration into applications.

@ -0,0 +1,3 @@
# GDPR in API Design
The General Data Protection Regulation (GDPR) is an essential standard in API Design that addresses the storage, transfer, and processing of personal data of individuals within the European Union. With regards to API Design, considerations must be given on how APIs handle, process, and secure the data to conform with GDPR's demands on data privacy and security. This includes requirements for explicit consent, right to erasure, data portability, and privacy by design. Non-compliance with these standards not only leads to hefty fines but may also erode trust from users and clients. As such, understanding the impact and integration of GDPR within API design is pivotal for organizations handling EU residents' data.

@ -0,0 +1,3 @@
# GraphQL APIs
GraphQL is an open-source data query and manipulation language for APIs, and a runtime for executing those queries with your existing data. Unlike REST, where you have predefined data return structures for each endpoint, GraphQL APIs are designed around a type system and enable the client application to precisely specify what data it needs from the server. This gives a lot of flexibility and efficiency, leading to fewer round trips to the server and significantly enhancing the performance of the client application. Whether you are building a small project or an enterprise-scale application, understanding and implementing GraphQL APIs can result in cleaner, more manageable code.

@ -0,0 +1,5 @@
# Handling CRUD Operations in API Design
When designing APIs, one needs to account for various types of interactions with data - these typically revolve around the CRUD operations; Create, Read, Update, and Delete. Whether the API is designed for a banking app or a social media platform, the need to create new data, read or retrieve existing data, update or modify that data, and delete unnecessary data is universal.
Therefore, mastering CRUD operations in API design is a fundamental skill. Effective handling of CRUD operations facilitates seamless interaction between the front-end and back-end systems, and ensures proper data management, thereby improving user experience.

@ -0,0 +1,3 @@
# HATEOAS in API Design
Hypertext As The Engine Of Application State (HATEOAS) is a key concept in the design of RESTful APIs (Application Programming Interfaces). It implies that the API delivers data as well as information about available interactions. By utilizing hypermedia, it contributes to the self-descriptiveness and discoverability of the API. When correctly implemented, clients only need generic knowledge about hypermedia, not specific API semantics, which can significantly simplify client implementations and make APIs more flexible to changes. The principle of HATEOAS can enforce a more structured, standardized approach to API design and development.

@ -0,0 +1,3 @@
# HIPAA in API Design
HIPAA (Health Insurance Portability and Accountability Act) is a critical standard when it comes to API design in the healthcare industry. In essence, it provides the mandate for protecting sensitive patient data. Any organization dealing with protected health information (PHI) must ensure all required physical, network, and process security measures are in place. In the context of API design, HIPAA compliance means structuring endpoints, data transmission, and storage methods that align with these crucial safeguards. This encompasses encryption, access controls, audit controls, and integrity controls. Hence, understanding HIPAA is fundamental for API designers working in the healthcare domain.

@ -0,0 +1,3 @@
# HTTP Caching in API Design
HTTP caching is a key aspect of API design which involves storing copies of responses to HTTP requests to speed up future requests. When an API receives the same request multiple times, instead of processing each request separately, it can use a previously stored response, thereby improving performance and efficiency. The cache is governed by headers on the HTTP requests and responses. Understanding and implementing HTTP caching in API design can drastically reduce latency, network traffic and improve the speed of an API.

@ -0,0 +1,3 @@
# HTTP Headers in API Design
HTTP Headers play a crucial role in API Design as they provide essential information between the client and server regarding the data to be exchanged. Headers are part of the HTTP request and response message, with types including Standard, Non-standard, Common or Uncommon headers. They can define parameters such as content type, authentication, response status, cookies, and more. Understanding and effectively utilizing HTTP Headers is key to designing robust and secure APIs. A well-defined set of headers ensures successful data exchange, handles errors gracefully, and improves overall communication between the client and server.

@ -0,0 +1,3 @@
# HTTP Methods
HTTP (Hypertext Transfer Protocol) Methods play a significant role in API design. They define the type of request a client can make to a server, providing the framework for interaction between client and server. Understanding HTTP methods is paramount to creating a robust and effective API. Some of the common HTTP methods used in API design include GET, POST, PUT, DELETE, and PATCH. Each of these methods signifies a different type of request, allowing for various interactions with your API endpoints. This in turn creates a more dynamic, functional, and user-friendly API.

@ -0,0 +1,3 @@
# HTTP Status Codes
HTTP Status Codes are an essential part of API Design, providing important information about the result of a request made to a server. They are 3-digit numbers where the first digit defines the class of response, while the last two digits do not have any categorization value. For instance, '200' stands for a successful HTTP request, while '404' signifies that a requested resource could not be found on the server. Efficient use of these codes can enhance API's robustness, making it more understandable and easier to debug.

@ -0,0 +1,3 @@
# HTTP Versions in API Design
HTTP or Hypertext Transfer Protocol is pivotal in the world of API design. HTTP versions specify how data should be packaged and transported, as well as how web servers and browsers should respond to commands. Understanding different HTTP versions and their features is essential for API designers as it directly impacts how well an API can communicate with other software and systems. From HTTP/1.0, the initial version of HTTP to HTTP/2 and the latest version HTTP/3, each version brings in improvements in speed, data transmission capabilities, and security. Selecting an appropriate HTTP version is crucial for API efficiency and performance.

@ -0,0 +1,3 @@
# HTTP in API Design
HTTP, or Hypertext Transfer Protocol, is a fundamental piece of any API design. It is the protocol used for transmitting hypermedia data on the web, such as HTML webpages or JSON from a web API. Understanding HTTP is crucial in API design as it provides the structure for how requests and responses should be constructed and handled. It dictates how endpoints are defined, how data should be transferred, and what status codes should be used to convey specific scenarios. A solid grounding in HTTP principles allows for more robust, efficient and secure API designs.

@ -0,0 +1,3 @@
# Idempotency in API Design
Idempotency in API design refers to the concept where multiple identical requests have the same effect as a single request. This means that no matter how many times a client sends the same request to the server, the server's state stays the same after the first request. Designing APIs to be idempotent is essential for reliability, as it allows retries without side-effects, reduces complexity in distributed systems, and provides better user experience in unstable network conditions. Understanding idempotency concepts can increase the robustness and fault tolerance of your APIs. It is usually applicable to `PUT`, `DELETE`, and sometimes `POST` methods in RESTful APIs.

@ -0,0 +1,3 @@
# Integration Testing in API Design
Integration testing is a critical aspect of API design. It is a level of software testing where individual units or components are combined and tested as a group. The main purpose of integration testing in API design is to expose faults and discrepancies in the interaction between integrated units. This testing approach ensures that the different parts of an API work together seamlessly, to deliver the necessary functionality and performance. It helps detect issues related to the network, database, and performance, which unit tests cannot uncover. Thus, this level of testing is instrumental in validating the reliability, efficiency, and functionality of an API's integrated components.

@ -0,0 +1,3 @@
# JSON Web Token (JWT) in API Design
JSON Web Tokens, or JWT, are a popular and secure method of transferring information between two parties in the domain of API design. As a compact, URL-safe means of representing claims to be transferred between two parties, they play a vital role in security and authorization in modern APIs. By encoding these claims, the information can be verified and trusted with a digital signature - ensuring that the API end-points can handle requests in a secure and reliable way. JWT is a relatively lightweight and scalable method that brings improved authentication and information exchange processes in API design.

@ -0,0 +1,3 @@
# Kafka in API Design
Apache Kafka is a real-time, fault-tolerant, and highly reliable messaging system that's integral to API design. It's primarily used to build real-time data streaming applications and microservices due to its inherent ability to handle high volume data and multi-subscriber support. In the context of API design, Kafka provides a robust messaging queue system that enables cloud-based platforms and services to communicate seamlessly with each other in a real-time environment. Moreover, the API designers use Kafka APIs such as Producer API, Consumer API, Streams API, and Connect API which enable the transmission and manipulation of messages within the Kafka ecosystem.

@ -0,0 +1,3 @@
# Learn the Basics of API Design
Application Programming Interfaces (APIs) are an integral part of modern development, allowing software applications to communicate and use functions from other software applications or services. API design, therefore, becomes a key part of any software development process. Furthermore, the basics of API design encompass understanding the principles of what an API is, how it works, and the various types of APIs, such as REST, SOAP, and GraphQL. This also includes understanding the standards and best practices in API design to ensure the development of powerful, user-friendly, and secure APIs. The foundation of API Design lies in this knowledge, setting the stage for more complex API designing and development.

@ -0,0 +1,3 @@
# Load Balancing in API Design
Load Balancing plays a crucial role in the domain of API Design. It primarily revolves around evenly and efficiently distributing network traffic across a group of backend servers, also known as a server farm or server pool. When it comes to API design, implementing load balancing algorithms is of immense importance to ensure that no single server bears too much demand. This allows for high availability and reliability by rerouting the traffic in case of server failure, effectively enhancing application performance and contributing to a positive user experience. Therefore, it's a vital tactic in ensuring the scalability and robustness of system architectures which heavily rely on API interactions.

@ -0,0 +1,3 @@
# Load Testing in API Design
Load testing is a crucial aspect of API design that ensures reliability, efficiency and performance under varying loads. It primarily focuses on identifying the maximum capacity of the API in terms of the volume of requests it can handle and its subsequent behavior when this threshold is reached or overloaded. By simulating varying degrees of user load, developers can identify and rectify bottlenecks or breakdown points in the system, hence enhancing overall API resilience.

@ -0,0 +1,3 @@
# Messaging Queues in API Design
Messaging Queues play a fundamental role in API design, particularly in creating robust, decoupled, and efficient systems. These queues act like a buffer, storing messages or data sent from a sender (producer), allowing a receiver (consumer) to retrieve and process them at its own pace. In the context of API design, this concept enables developers to handle high-volume data processing requirements, providing an asynchronous communication protocol between multiple services. The benefits of messaging queues in API design include better system scalability, fault tolerance, and increased overall system resiliency.

@ -0,0 +1,3 @@
# Microservices Architecture
When it comes to API Design, Microservices Architecture plays a crucial role. It represents a unique method of developing software systems that focuses on building single-function modules with well-defined interfaces. Each microservice runs a unique process and communicates through a well-defined, lightweight mechanism (often HTTP resources API) to serve a specific business goal. This architecture allows rapid, reliable, and scalable deployment of large, complex applications. It facilitates the organization of the development team around independently deployable units, thereby enhancing productivity and speed. When designing an API, it's essential to adapt this model to get a flexible and scalable construction.

@ -0,0 +1,3 @@
# Mocking APIs under API Testing
API mocking is a crucial aspect of API design and testing. It involves simulating the behaviors of real APIs to test various aspects of the system without the need of the real API being readily available. During the stages of development and testing, the API might be undefined or changes in the API can be expected, hence mocking comes into the picture. In such cases, it helps software developers and testers to isolate the system and work independently, enhancing the control over the input and output of the test. The focus here ranges from testing the API for functionality, reliability, performance, to security. Therefore, understanding and implementing effective API mocking strategies can significantly streamline the API design and development process.

@ -0,0 +1,3 @@
# OAuth 2.0
OAuth 2.0 is an authorization framework that allows applications to obtain limited access to user accounts on an HTTP service, such as Facebook, GitHub, DigitalOcean, and others. It works by delegating user authentication to the service that hosts the user account and authorizing third-party applications to access the user account. OAuth 2.0 defines four roles: resource owner, client, resource server and authorization server. With regards to API design, OAuth 2.0 can be used to protect API endpoints by ensuring that the client applications having valid access tokens can only interact with the API. It provides detailed workflow processes and a set of protocols for the client application to get authorization to access resources.

@ -0,0 +1,3 @@
# Pagination in API Design
Pagination is a crucial aspect of API design, providing a systematic approach to handling large amounts of data in a manageable way. Instead of returning all data in a single response, which can be overwhelming and inefficient, APIs implement pagination to deliver this data in smaller, more convenient parcels. This allows client applications to fetch data incremently and only as needed, greatly enhancing performance and usability. The design and implementation of pagination can vary, with different strategies such as limit-offset, cursor-based, or time-based pagination, each with its own set of advantages and limitations. An effective API design should carefully consider pagination style, striving for a balance between ease of use, efficiency, and scalability.

@ -0,0 +1,3 @@
# PCI DSS in API Design
Payment Card Industry Data Security Standard (PCI DSS) is a widely accepted set of policies and procedures intended to optimize the security of credit, debit and cash card transactions and protect cardholders against misuse of their personal information. In terms of API Design, building APIs in compliance with PCI DSS is crucial when processing, storing or transmitting credit card information. By adhering to these standards, not only can developers ensure safe and secure API endpoints but also build trust among users by safeguarding their sensitive financial data.

@ -0,0 +1,3 @@
# Performance Metrics in API Design
API Design performance metrics play a critical role in ensuring APIs are efficient, effective, and absolutely fit for their intended purpose. The performance of an API can profoundly impact the user experience and overall system performance. Therefore, it is crucial to define and monitor a set of performance metrics. These may include response times, throughput, error rates, and others that measure system health and resource utilization. By prioritizing these metrics in the context of API Design, developers can create APIs that not only meet functional requirements but also deliver desired performance levels.

@ -0,0 +1,3 @@
# Performance Testing in API Design
Performance Testing in API design refers to the practice of evaluating and ensuring that an API operates reliably and efficiently under varying workloads. Properly conducted performance testing can verify an API's speed, response time, reliability, and scalability. As an integral aspect of API design, it checks if API's are effectively meeting expectations for system functionality and demonstrates the potential areas of optimization. Performance testing is essential in maintaining high standards of user experience by preventing unexpected failures, and optimizing API consumer satisfaction.

@ -0,0 +1,3 @@
# PII under Standards and Compliance
Personal Identifiable Information (PII) under Standards and Compliance is a crucial aspect of API Design. It refers to the secure handling and transmission of personal data such as names, addresses, and credit card numbers, which APIs often deal with. In this context, APIs must be built under strict compliance with standards such as GDPR, HIPAA or PCI DSS, which regulate the protection of personal data. These standards ensure that personal data is not misused and that user privacy is respected. Any violations can lead to hefty fines and damage to the company's reputation. Understanding PII and designing APIs in accordance with applicable regulations is vital for a robust, secure, and compliant API design.

@ -0,0 +1,3 @@
# Postman in API Design
Postman is a popular tool in web development for designing, testing, and managing APIs. As a collaborative platform, it simplifies each step of the API lifecycle and streamlines collaboration across teams. In context of API design, it can be employed to design and mock APIs, automate testing, and observe responses in a user-friendly interface. API endpoints can be organized into collections also in Postman for a well-structured and organized API design process. Ultimately, its user-friendly interface and comprehensive features position Postman as an indispensable tool in the realm of API design.

@ -0,0 +1,3 @@
# Profiling and Monitoring in API Design
Profiling and monitoring are critical aspects of API design and implementation. Profiling, in this context, refers to the process of analyzing the behavior of your API in order to understand various performance metrics including response times, request rates, error rates, and the overall health and functionality of your API. On the other hand, monitoring is the ongoing process of checking the status of your API to ensure it's functioning as expected while also providing an early warning system for potential issues and improvements. Together, profiling and monitoring your API can lead to a more reliable, efficient, and high-performing service.

@ -0,0 +1,5 @@
# RabbitMQ in API Design
RabbitMQ is an open-source message-broker software/system that plays a crucial role in API design, specifically in facilitating effective and efficient inter-process communication. It implements the Advanced Message Queuing Protocol (AMQP) to enable secure and reliable data transmission in various formats such as text, binary, or serialized objects.
In API design, RabbitMQ comes in handy in decoupling application processes for scalability and robustness, whilst ensuring that data delivery occurs safely and seamlessly. It introduces queuing as a way of handling multiple users or service calls at once hence enhancing responsiveness and performance of APIs. Its queue system elegantly digests API request loads, allowing services to evenly process data while preventing overloading.

@ -0,0 +1,3 @@
# Rate Limiting / Throttling in API Design
Rate Limiting, often referred to as Throttling, is a fundamental aspect of API Design aimed at controlling the number of requests a client can make to an API within a specified timeframe. This technique ensures fair usage, enhances security, prevents server overload, and allows an even distribution of resources. It also minimizes the risks associated with abusive behaviors or DDoS attacks. Effective rate limiting strategy involves defining the limits based on the API's capacity and clients' reasonable needs, with flexibility to tweak these limits when necessary. Understanding rate limiting and its significance is crucial for building resilient, secure, and scalable API platforms.

@ -0,0 +1,3 @@
# Readme.com in the Context of API Design
Readme.com is an invaluable tool in the realm of API Design, renowned for providing a collaborative platform for creating beautiful, dynamic and intuitive documentation. It's a tool which aids developers in outlining clear, comprehensive documentation for their API interfaces. The API documentation created with Readme.com is not just about the presentation of information, but enhances the reader's understanding by making it interactive. This interactive approach encourages practical learning and offers insights into how the API will behave under different circumstances. With Readme.com, developers can create a user-focused documentation environment that streamlines the learning process and makes their APIs easier to consume and implement.

@ -0,0 +1,3 @@
# Real-time APIs
In the realm of API Design, Real-time APIs hold significant value as they provide immediate access to the latest data as soon as they become available. Rather than relying on periodic polling for updates, Real-time APIs maintain an open connection between the client and the server which allows immediate, bi-directional data flow. These APIs are commonly used in applications which require real-time information such as live chat programs, financial trading platforms or online multiplayer games. Designing such APIs requires careful consideration of factors such as connection management, data consistency, and efficient handling of high volume data streams.

@ -0,0 +1,3 @@
# Rate Limiting in API Design
Rate Limiting is a critical aspect of API Design that dictates the number of API calls a client can make within a specified timeframe. This helps in managing resource allocation, preventing abuse of the API, and maintaining the overall health of the API system. Proper rate limiting measures should be in place to ensure the API's stability, thereby delivering a consistent and reliable service to all consumers. It works primarily by setting a limit on the frequency of client requests, thereby preventing individual users from overloading the system. It is crucial to design and implement rate limiting carefully for maintaining API availability and performance.

@ -0,0 +1,3 @@
# REST Principles in API Design
REST (Representational State Transfer) is an important architectural style used in API design. It defines a set of rules and conventions through which systems communicate over a network. Key characteristics of REST include statelessness, client-server communication, cacheability, and a uniform interface. Understanding and applying these principles properly can help in designing robust, scalable, and high-performance APIs. REST principles revolve around resources and their manipulation to achieve desired outcomes. By following these principles, developers can ensure that their API design is in line with web standards, thus improving interoperability across different systems.

@ -0,0 +1,3 @@
# RESTful APIs
RESTful APIs, or Representational State Transfer APIs, are a set of conventions for designing networked applications. They utilize HTTP methods to read, update and delete data. They offer a simple and standardized way to build web services that can be easily consumed by different clients. The key principles of a RESTful API include stateless client-server communication, cacheable data, and a uniform interface, making the API easy to understand, flexible, and scalable. Moreover, it relies heavily on the use of resources and their representations, making it a popular choice in API design due to its performance, scalability, simplicity, and reliability.

@ -0,0 +1,3 @@
# RFC 7807 - Problem Details for HTTP APIs in Error Handling
The practice of API Design includes a significant focus on handling errors effectively and transparently. Among the widespread standards being adopted, the RFC 7807 or Problem Details for HTTP APIs plays a crucial role. This specification provides a standardized format for sending problem or error details from an HTTP API so developers engaging with the API do not need to parse non-standard error messages and can anticipate the structure of potential errors. In essence, RFC 7807 improves the usability and comprehension of your API, providing a better developer experience and encouraging the efficient use of your API. Implementing it paves the way to robust and accountable systems, where issues can be traced, identified, and solved more conveniently.

@ -0,0 +1,3 @@
# Role Based Access Control (RBAC) in API Design
Role-Based Access Control (RBAC) is a method of managing authorization in API design that assigns system access to users based on their role within an organization. RBAC is crucial in controlling which endpoints a user can call, and what operations they are allowed to execute. In the context of API design, RBAC ensures appropriate levels of access for different types of users to guarantee data security and integrity. It simplifies the process of security administration by assigning privileges based on a user's job function, rather than on an individual basis.

@ -0,0 +1,3 @@
# Server Sent Events under Real-time APIs
Server-Sent Events (SSE) represent an explicit concept in the design of Real-time APIs. Unlike traditional approaches where a client sends a request and awaits a response from the server, SSE enables a server to push data to clients whenever a particular event takes place. SSE is especially fundamental in API design when it comes to the development of applications where real-time data is essential, such as live news updates, real-time gaming, or live-streaming services. Designing APIs with the SSE approach ensures a more dynamic and responsive user experience.

@ -0,0 +1,7 @@
# Session Based Authentication in API Design
Application Programming Interfaces (APIs) are critical for building software applications. Among several key considerations during API design, one is deciding how to implement authentication and security. Session Based Authentication is one popular way to apply security in API design.
This method revolves around the server creating a session for the user after they successfully log in, associating it with a session identifier. This Session ID is then stored client-side within a cookie. On subsequent requests, the server validates the Session ID before processing the API call. The server will destroy the session after the user logs out, thereby invalidating the Session ID.
Understanding Session Based Authentication is crucial for secure API design, especially in scenarios where security is a top priority or in legacy systems where this method is prevalent.

@ -0,0 +1,3 @@
# Simple JSON APIs
Simple JSON (JavaScript Object Notation) APIs are a popular form of API or "Application Programming Interface" which utilise JSON to exchange data between servers and web applications. This method has gained prominence mainly for its simplicity, light weight, and easy readability. In the context of API design, a well-structured JSON API allows developers to efficiently interact with the backend and retrieve only the data they need in a consistent and comprehensible manner. From reducing redundant data to enabling quick parsing, Simple JSON APIs provide numerous benefits to improve the overall performance of applications. Designing a good JSON API requires careful planning, sound knowledge of HTTP methods, endpoints, error handling mechanisms, and most importantly, a clear understanding of the application's data requirements.

@ -0,0 +1,3 @@
# SOAP APIs
SOAP (Simple Object Access Protocol) APIs are a standard communication protocol system that permits programs that run on different operating systems (like Linux and Windows) to communicate using Hypertext Transfer Protocol (HTTP) and its Extensible Markup Language (XML). In the context of API Design, SOAP APIs offer a robust and well-defined process for interaction between various software applications, mostly over a network. They are highly extensible, versatile and support a wide range of communications protocols. Despite being more complex compared to other API types like REST, SOAP APIs ensure high reliability and security, making them the choice for certain business-focused, high-transaction applications.

@ -0,0 +1,7 @@
# Standards and Compliance in API Design
When designing APIs, it's crucial to consider the concept of standards and compliance. Standards represent the set of rules and best practices that guide developers to create well-structured and easily maintainable APIs. They can range from the proper structure of the endpoints, the standardization of error responses, to naming conventions, and the usage of HTTP verbs.
Compliance on the other hand, emphasizes on meeting protocol requirements or standards such as REST or SOAP. Furthermore, operating within regulated industries can also necessitate certain compliance measures like GDPR, HIPAA and others. Compliance in API Design ensures interoperability and safety of data transmission between systems.
In essence, Standards and Compliance in API Design contributes towards building more secure, robust, and efficient APIs that are user-friendly and universally understandable.

@ -0,0 +1,3 @@
# Stoplight API Design
Stoplight is an advanced tool that offers a comprehensive platform for technical teams to handle all aspects of API design. Leveraging Stoplight, teams can design, document and develop APIs in a more collaborative and streamlined manner. It uses an OpenAPI specification and allows users to design APIs visually, making API development easier. With its ability to auto-generate API documentation, performing API mock testing, and providing API management features, Stoplight plays a crucial role in adopting a design-first approach in API development. By using Stoplight, APIs can be designed to be easy-to-use, scalable, and robust from the outset, which ultimately improves the overall development process and quality of the APIs.

@ -0,0 +1,3 @@
# Swagger / Open API
Swagger, also known as OpenAPI, is a set of tools specifically used for designing, building, and documenting RESTful Web services. API developers heavily rely on it due to its incredible feature for designing APIs with a clear and easy-to-understand approach. By utilizing the OpenAPI Specification (OAS), developers can accurately define a RESTful API that can easily be used across various programming languages. This powerful universal language is a key component for effective and efficient API design.

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

Loading…
Cancel
Save